当寻找一种优雅的方式来从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
}
}
}