我正在使用dotnet core 2.2,并且具有以下UDP侦听器:
var socket = new Socket(ep.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
while (true)
{
var result = await socket.ReceiveFromAsync(...);
}
现在在某些情况下,我想打断ReceiveFromAsync()
通话。但是似乎与TCP情况(即ReceiveAsync()
)不同,没有ReceiveFromAsync()
重载接受CancellationToken
。
一种选择是将Task.Delay(-1, ct);
与Task.WhenAny()/Task.WhenAll()
一起使用。但是我认为这种解决方案会导致内存泄漏,对吗?我的意思是.ReceiveFromAsync()
调用如果被中断,即使在后台也仍然“存在”。还可能导致逻辑中断,因为此类调用将读取UDP数据包并随后将其丢弃?还是我的推理不正确?
另一种想法是让后台工作程序从UDP套接字读取数据并将每个数据包排队。而且这里不会发生任何中断。然后,我将从队列中读取并中断此调用。那会起作用,但绝对需要一些努力。我看到的问题是:线程安全性和性能。
是否有一种更清洁/更简便的方法来处理这种情况?
答案 0 :(得分:1)
对于“无法取消的” I / O请求,Windows中的标准模式是关闭基础句柄-在这种情况下为套接字。通常,这会导致所有异步(或同步)操作以错误代码完成。
在您的情况下-“暂停” UDP接收器-我认为这种方法特别有意义。 UDP套接字无论如何都不代表打开的连接,因此关闭套接字是最好的解决方案。
关于Task.Delay
与Task.WhenAny
,您的担心是完全正确的。 Task.Delay
+ Task.WhenAny
方法仅取消操作的 wait ,而不取消操作本身。具体来说,它不会取消UDP接收,并且未取消UDP接收操作可能会得到一个数据包,然后该数据包将被“丢失”,因为您的应用程序会忽略它。