async 比 BeginXXX/EndXXX 有什么优势?

What is the advantage of async over BeginXXX/EndXXX?

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

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

然而,

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

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

好吧,不是分配一个线程池线程等待异步操作完成。相反,它分配一个线程池线程来 start 异步操作,而不是在当前线程中启动它。

确实没有任何理由这样做,至少除非启动异步操作的行为需要很长时间,而且如果编写正确则不应该这样做。

你能在不在线程池线程中启动异步操作的情况下实现同样的事情吗,当然,只需删除在线程池线程中启动它的代码。

首先,在自然异步 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
        }
    } 
}