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

问题描述 投票:1回答:1

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

根据这个问题Do I need to dispose of a Task?和根据这个博客Parallel Programming with .NET Tasks不需要是Disposed。但是,我有时会每秒实例化数千个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中也发生了变化。

问题:我是否需要在此特定情况下处理Tasks?我是否会创建许多Handles,如果我没有Dispose TaskCompletionSource创建的任务收到沿此代码路径的许多数据包?这是博客条目警告我的情景吗?

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

.net task dispose taskcompletionsource
1个回答
2
投票

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

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

分配WaitHandle的唯一方法是,如果你明确要求Task的IAsyncResult.AsyncWaitHandle,那应该是非常罕见的。

Reed's answer当时是正确的,但不再是继续使用AsyncWaitHandle的情况。这些天,没有任何东西会隐式使用AsyncWaitHandle,所以你应该只考虑Disposeing Tasks,如果你的消费代码将任务视为IAsyncResult并访问AsyncWaitHandle属性。即便如此,你应该只考虑处理它们;这不是绝对必要的。

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.