只有在Windows XP上异步接收UdpClient异常

本文关键字:UdpClient 异常 异步 Windows XP | 更新日期: 2023-09-27 18:05:50

我有一个c#代码在Windows vista/7上运行得很好,但在Windows XP上就不行了。

有问题的部分是一个"多播"节点,它基本上通过多播地址+端口读取和发送数据。

向网络读写的部分是一个单例。

每个访问此单例的线程都必须指明何时需要开始侦听,何时需要停止侦听。

当至少有一个线程需要"启动"时监听套接字,当所有线程"停止"时停止(它们必须给出一个Guid令牌,Start方法返回)。

这个启动/停止机制是为了确保如果没有线程需要查看网络上正在发生的事情,我们不会为此消耗内存。

我得到的问题是,在windows XP上,我得到了这个例外:

System.Net.Sockets.SocketException (0x80004005): The I/O operation has been aborted because of either a thread exit or an application request
   at System.Net.Sockets.Socket.EndReceiveFrom(IAsyncResult asyncResult, EndPoint& endPoint)
   at System.Net.Sockets.UdpClient.EndReceive(IAsyncResult asyncResult, IPEndPoint& remoteEP)

经过一番搜索,在windows XP及以下版本中,当一个线程结束时,操作系统释放所有的I/O资源。(VB。. NET 3.5 SocketException(在部署机而不是开发机上).

有办法避免这种行为吗?因为在我的例子中,我创建的线程通常会在执行结束之前结束,而我不想让它的套接字被释放?

如果不可能,你将如何处理?

只有在Windows XP上异步接收UdpClient异常

异步操作的调用线程在操作完成之前被终止。

异步I/O操作使用IOCP (I/O完成端口)机制,当I/O操作结束时通知执行线程。

在幕后,整个事情是基于一种叫做重叠I/O的东西。在Windows Vista中,重叠i/o的行为被改变了,所以当调用线程终止时,i/o操作不再被取消。

在Windows Vista之前(例如,XP),每当调用线程终止任何由该线程发起的重叠i/o时,该线程将被取消,这可能是导致此异常的原因。

您可以在这里阅读更多信息:http://www.lenholgate.com/blog/2008/02/major-vista-overlapped-io-change.html

您不能重写此行为,但您可以确保(例如使用事件)您不会尝试使用创建线程不再活动的任何I/O资源。

所以这似乎是由于windows XP在线程结束时自动释放线程创建的资源(VB)。. NET 3.5 SocketException(在部署机而不是开发机上).

所以,我的解决办法是有一个具有IsBackground属性设置为true的线程,即在BlockingCollection上迭代。当我需要监听另一个IP时,我将这个IP添加到阻塞集合中,该线程创建它。

由于这个线程在整个应用程序生命周期中永远不会结束,所以资源不会被释放。我已经使这个行为检查Environment.OSVersion.Version.Major更大或等于6,这是Vista的版本号。

现在它就像一个魅力在所有版本

在较新的。net框架版本中,这将起作用。

TaskEx.Run(() => _udp.BeginReceive(AsyncCallback, state)).ConfigureAwait(false);