如何在另一个线程中继续 TaskCompletionSource<>?

How to continue TaskCompletionSource<> in another thread?

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

那些 "SubConnections"(正在通过 await 等待)然后应该在一个新线程中继续。

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

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

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

的线程中继续

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

我的主要问题是:我将如何以 "best practice" 方式执行此操作?

我在这里的希望也是避免 ThreadPool 开销,因为与仅阻塞线程并等待 ManualResetEvent 相比,它在 Linux 上相当高 - 即使 SynchronizationContext (或其他)也可以使用 ThreadPool.

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

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

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

参见例如了解更多详情。