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

时间:2019-02-18 21:49:43

标签: .net task dispose taskcompletionsource

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

根据此问题Do I need to dispose of a Task?,根据此博客Parallel Programming with .NET TaskDispose不需要。但是,有时我每秒实例化数千个TaskCompletionSource。链接博客中的详细答案还说,Task可能在内部使用WaitHandle。现在,我有一种很强烈的感觉,就是我的情况就是确切的情况,我应该在Dispose中的任务上使用TaskCompletionSource

这就是我等待新数据包的方式。此方法将被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;
}

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

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

我在.NET Core> = 2.2上。该博客条目指出WaitHandle的行为在.NET 4.5中也已更改。

问题:在这种特定情况下,我是否需要处置Task?如果我在收到许多沿此代码路径传入的数据包时不Handles创建Dispose的任务,是否会创建许多TaskCompletionSource?博客条目警告过我的是这种情况吗?

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

1 个答案:

答案 0 :(得分:2)

  

这是博客条目警告我的情况吗?

“我需要处置此Task吗?”的问题。只能通过消耗的方式来回答。特别要考虑博客文章中的这句话:

  

分配WaitHandle的唯一方法是,如果您明确要求Task的IAsyncResult.AsyncWaitHandle,那应该很少。

Reed's answer在当时是正确的,但继续使用AsyncWaitHandle的情况已不再如此。如今,没有任何内容会隐式使用AsyncWaitHandle,因此,如果您的消耗代码将任务视为{{1 }} 访问Dispose属性。即使这样,您也应该考虑处置它们;并非完全不必要

  

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

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

此外,如果您经常希望自己的Task方法已经有可用的数据包,则可以考虑使用IAsyncResult