2

我的 ac# 代码在 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 在部署但不在开发机器上)。

有没有办法避免这种行为?因为在我的情况下,我创建一个在执行结束之前结束的线程是很正常的,而且我不想释放它的套接字?

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

4

3 回答 3

2

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

异步 I/O 操作使用称为 IOCP(I/O Completion Port)的机制在 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 资源。

于 2013-03-25T13:20:30.800 回答
1

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

因此,我的解决方法是让一个线程将IsBackground属性设置为 true,即在 BlockingCollection 上进行迭代。当我需要再听一个 IP 时,我将这个 IP 添加到阻塞集合中,这个线程会创建它。

由于该线程在整个应用程序生命周期中永远不会结束,因此不会释放资源。我已将此行为检查Environment.OSVersion.Version.Major为大于或等于 6,即 Vista 版本号。

现在它就像所有版本的魅力一样工作

于 2013-04-26T13:54:51.673 回答
0

在较新的 .NET FrameWork 版本上,这可以解决问题。

TaskEx.Run(() => _udp.BeginReceive(AsyncCallback, state)).ConfigureAwait(false);
于 2015-05-19T09:18:55.833 回答