我的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 on deployment but not on development machine)。
有没有办法避免这种行为?因为在我的情况下,这是正常的,并且通常我创建一个将在执行结束之前结束的线程,并且我不想释放它的套接字?
如果不可能,您将如何处理?
答案 0 :(得分:2)
异步操作的调用线程在操作完成之前终止。
异步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资源。
答案 1 :(得分:1)
所以这似乎是由于Windows XP在线程结束时自动释放线程创建的资源(VB.NET 3.5 SocketException on deployment but not on development machine)。
所以,我的解决方法是让一个IsBackground
属性设置为true的线程,即迭代BlockingCollection。当我需要再听一个IP时,我在阻塞集合上添加了这个IP,这个线程创建了它。
由于此线程永远不会在整个应用程序生命周期中结束,因此不会释放资源。我已经做了这个行为,检查Environment.OSVersion.Version.Major
是大于还是等于6,这是Vista的版本号。
现在它就像所有版本的魅力一样
答案 2 :(得分:0)
在较新的.NET FrameWork版本上,这将起到作用。
TaskEx.Run(() => _udp.BeginReceive(AsyncCallback, state)).ConfigureAwait(false);