0

TaskCompletionSource<>经常使用。我有一个网络协议设计,我在一个 tcp/ip 连接中接收到许多流。我对这些流进行解复用,然后将新内容通知相应的“子连接”。

那些“子连接”(通过 等待await)然后应该在新线程中继续。

通常我通过将TaskComplectionSource<>.Set调用放在匿名ThreadPool.QueueUserWorkItem方法中来解决此类问题,如下所示:

ThreadPool.QueueUserWorkItem(delegate { tcs.SetResult(null); });

如果我不这样做,相应的await tcs.Task调用将在调用的线程中继续tcs.SetResult

但是,我知道这不是做事的正确方法。也可以自己编写一个SynchronizationContext(或其他东西)来指示await调用在另一个线程中继续。

我的主要问题是:我将如何以“最佳实践”的方式做到这一点?

我希望在这里也能避免ThreadPool开销,因为与阻塞线程并等待ManualResetEvent- 即使SynchronizationContext(或其他)也可能使用ThreadPool.

请不要告诉我在一个 tcp/ip 连接中多路复用某些东西通常是一个坏主意,或者我应该只使用 System.IO.Pipelines、REST 或其他什么。这是我的场景。谢谢你。

4

1 回答 1

1

您可以创建TaskCompletionSource使用TaskCreationOptions.RunContinuationsAsynchronously(在 .NET 4.6+ 中):

var tcs = new TaskCompletionSource<Result>(TaskCreationOptions.RunContinuationsAsynchronously);
...
tcs.SetResult(...);

有关更多详细信息,请参见例如此线程

于 2020-01-08T11:51:56.960 回答