c# - 如何取消 Socket.ReceiveFromAsync()?
问题描述
我正在使用 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 套接字读取数据并对每个数据包进行排队。并且这里不会发生中断。然后我会从队列中读取并中断这个呼叫。这会奏效,但肯定需要一些努力。我看到的问题是:线程安全和性能。
有没有更清洁/更简单的方法来处理这种情况?
解决方案
对于“不可取消”的 I/O 请求,Windows 中的标准模式是关闭底层句柄——在本例中为套接字。这通常会导致任何异步(或同步)操作以错误代码完成。
在您的情况下-“暂停” UDP 接收器-我认为这种方法特别有意义。无论如何,UDP 套接字并不代表打开的连接,因此关闭套接字是最好的解决方案。
关于Task.Delay
with Task.WhenAny
,您的担忧是完全正确的。Task.Delay
+Task.WhenAny
方法只取消操作的等待,而不是操作本身。具体来说,它不会取消 UDP 接收,并且未取消的 UDP 接收操作可能会获得一个随后会“丢失”的数据包,因为您的应用程序会忽略它。
推荐阅读
- xml - 单行 xpath 提取命令行工具
- swift - Swift 如果 json 键与我创建的响应结构不匹配怎么办?
- reactjs - “未找到模块”来自 index.js 的反应加载类
- python - 如何在散景表中删除 NaN
- c# - Microsoft Dynamics 365 CRM 身份验证的示例代码,然后重定向到 C# 控制台应用程序
- outlook - LotusScript 在 MS Outlook 中创建日历条目
- ios - 如何通过 UIWebView 在 iOS 应用程序上上传外部文件?
- r - 如何在 R 中分组和取消分组?
- r - 如何在 R 中 2 个列表的元素之间应用函数?
- java - WARNING: No mapping for GET /StudentCurd/ (HTTP Status 404 – Not Found) 我已经尝试了所有的解决方案但无法解决这个问题,所以再次询问: