TaskCompletionSource 生成的任务是否需要进行 Dispose()d?

Sch*_*rle 6 .net dispose task taskcompletionsource

TaskCompletionSource在我的软件中使用将网络数据包分发到async/await方法。因此,在我的代码中,软件需要等待网络数据包从接收处理程序中解复用并移交给方法的多个点async Wait()。每秒可能有很多很多数据包,我正在决定是否要将数据包推送到TaskCompletionSource或将其放入Queue. 因此,只要没有,TaskCompletionSource我就会创建一个新的,这会导致一个新的Task对象。

根据这个问题Do I need to dispose of a Task? 根据此博客,不需要使用.NET 进行并行编程 。然而,我有时每秒实例化数千个。链接博客中的详细答案还说,可以在内部使用。现在我有一种强烈的感觉,我的情况就是确切的情况,我应该在.TaskDisposeTaskCompletionSourceTaskWaitHandleDisposeTaskCompletionSource

这就是我等待新数据包的方式。该方法将被调用await,也可以被大量并行调用:

public async Task<Packet> Wait()
{
    Packet packet;

    lock (sync)
        if (packets.TryDequeue(out packet))
            return packet;
        else
            waiter = new TaskCompletionSource<Packet>();

    return await waiter.Task;
}
Run Code Online (Sandbox Code Playgroud)

我从网络处理程序推送数据包的方法如下所示:

public void Poke(Packet packet)
{
    lock (sync)
        if (waiter == null)
            packets.Enqueue(packet);
        else
            waiter.SetResult(packet);
}
Run Code Online (Sandbox Code Playgroud)

我使用的是 .NET Core >= 2.2。该博客文章指出,.NET 4.5 中的行为WaitHandle也发生了变化。

Task问题:在这种特定场景下我需要 Dispose 吗?Handles如果我不创建沿着此代码路径接收许多数据包时Dispose创建的任务,我会创建许多任务吗?TaskCompletionSource这是博客文章警告我的情况吗?

请不要告诉我,只要您不能告诉我一种与async/await模式非常兼容并且能够将这些数据包分发给各种选定侦听器的更好方法,这种方法就是一个糟糕的选择。也请不要告诉我,由于许多网络数据包而创建许多对象通常是一个坏主意。

Ste*_*ary 7

\n

这是博客文章警告我的情况吗?

\n
\n\n

Task“我需要处理这个吗?”的问题 只能通过任务如何消耗来回答来回答。特别是考虑博客文章中的这句话:

\n\n
\n

分配 WaitHandle 的唯一方法是明确请求 Task\xe2\x80\x99s IAsyncResult.AsyncWaitHandle,而这种情况应该很少见。

\n
\n\n

里德的答案当时是正确的,但现在不再是延续使用的情况了AsyncWaitHandle。如今,没有任何内容会隐式使用,因此如果您的使用代码将任务视为 an访问属性AsyncWaitHandle,则只应考虑Disposeing s 。即便如此,你也应该只考虑处理它们;这并不是绝对必要的TaskIAsyncResult AsyncWaitHandle

\n\n
\n

请不要告诉我,只要您不能告诉我一种与异步/等待模式非常兼容并且能够将这些数据包分发到各种选定的侦听器的更好方法,这种方法就是一个糟糕的选择。

\n
\n\n

我建议将异步兼容的生产者/消费者队列构建为单独的类型;我认为这将有助于您的代码更清晰。您可以使用BufferBlock<T>我的 AsyncEx 库中的异步队列类型或者使用异步兼容监视器构建您自己的队列类型。

\n\n

另外,如果您经常期望您的Wait()方法已经有一个可用的数据包,那么请考虑使用ValueTask<T>.

\n