我有一些库(套接字网络)代码,它们基于 TaskCompletionSource<T>
为挂起的请求响应提供了一个基于 Task
的 API。然而,TPL 中有一个烦恼,似乎不可能阻止同步延续。我希望 喜欢能够做的是:
TaskCompletionSource<T>
,是不应该允许来电者附加与 TaskContinuationOptions.ExecuteSynchronously
,或TaskContinuationOptions.ExecuteSynchronously
的方式设置结果(SetResult
/TrySetResult
) ,而是使用池具体来说,我遇到的问题是,传入的数据是由一个专门的读取器处理的,如果调用者可以连接到 TaskContinuationOptions.ExecuteSynchronously
,那么他们可以拖延读取器(这不仅仅影响到他们)。在此之前,我已经通过一些技巧来解决这个问题,这些技巧可以检测到是否存在 任何延续,如果存在的话,它会将完成推送到 ThreadPool
,但是如果调用者已经饱和了他们的工作队列,这会产生很大的影响,因为完成不会被及时处理。如果它们使用 Task.Wait()
(或类似的) ,那么它们本质上将自身死锁。同样,这就是为什么读取器在一个专用线程上而不是使用 worker 的原因。
因此,在我试图向 TPL 团队唠叨之前: 我是否缺少一个选项?
要点:
ThreadPool
作为实现,因为它需要在池达到饱和时工作下面的示例生成输出(订单可能因时间不同而不同) :
Continuation on: Main thread
Press [return]
Continuation on: Thread pool
问题在于随机调用方设法在“ Main thread”上获得了一个延续。在实际的代码中,这会打断主要读取器; 不好的事情!
密码:
using System;
using System.Threading;
using System.Threading.Tasks;
static class Program
{
static void Identify()
{
var thread = Thread.CurrentThread;
string name = thread.IsThreadPoolThread
? "Thread pool" : thread.Name;
if (string.IsNullOrEmpty(name))
name = "#" + thread.ManagedThreadId;
Console.WriteLine("Continuation on: " + name);
}
static void Main()
{
Thread.CurrentThread.Name = "Main thread";
var source = new TaskCompletionSource<int>();
var task = source.Task;
task.ContinueWith(delegate {
Identify();
});
task.ContinueWith(delegate {
Identify();
}, TaskContinuationOptions.ExecuteSynchronously);
source.TrySetResult(123);
Console.WriteLine("Press [return]");
Console.ReadLine();
}
}