当寻找一种优雅的方式来从UDP套接字异步接收数据报流时,我遇到了以下问题:How to use asynchronous Receive for UdpClient in a loop?

我了解第一个答案的优点,因为它们使用了熟悉的BeginReceive / EndReceive方法。这个解决方案很好,因为没有线程被阻塞。

但是,second answer提供了两种不同的Task-ish解决方案,一种使用ReceiveAsync,另一种使用同步Receive方法。我想知道在这种情况下的优势是什么。据我了解,即使在ReceiveAsync情况下,仍然有一个(线程池?)线程在等待着事情的发生。

在这种情况下使用异步方法是否有优势?如果不是,是否有一种方法可以使用Async方法来实现这种类型的模式,而不会增加线程,任务或其他阻塞对象的开销?

最佳答案

首先,在自然异步API中,在async-await(TAP)版本和Begin/End(APM)(There Is No Thread)中都没有阻塞线程。

但是,在这种特定情况下,链接的答案确实不必要地浪费了ThreadPool线程,应避免这种情况。

ReceiveAsync情况将操作的同步部分(直到await ReceiveAsync)卸载到ThreadPool线程。如果您要执行大量的CPU绑定操作,并且想要释放调用线程,这将很有用。似乎并非如此,因为除了创建客户端之外,没有其他事情要做。

您可以简单地删除Task.Run并使用async方法:

async Task ListenAsync(int port, CancellationToken token)
{
    using (var client = new UdpClient(port))
    {
        while (true)
        {
            var result = await client.ReceiveAsync().WithCancellation(token).ConfigureAwait(false);
            // process result.Buffer
        }
    }
}

09-07 01:15