如何关闭包含对NetworkStream.Read的阻塞调用的线程

时间:2012-09-12 09:08:24

标签: c# .net multithreading sockets

我正在查看一些我自己没有写过的代码,而我正试图了解导致应用程序崩溃的原因。

我认为可能归结为它如何处理资源和管理线程。

主父线程创建一个新的应用层客户端(TCPMonitor),然后创建另一个处理TCP套接字通信的类(TCPListen)。这个类产生一个新的线程循环,它创建一个新的TCP套接字客户端,该套接字上的读取网络流,然后调用同步阻塞Read()。

但是,如果发生网络错误连接,则会在TCPListen线程循环中捕获异常,并将事件提升回拥有类TCPMonitor。然后,TCPMonitor检查它是否包含活动的TCPListen实例,如果是,则调用Dispose()并将实例设置为Null。

此时TCPListen Read()肯定会在其阻塞调用中?如果是这种情况,我如何确保从父线程调用Dispose会破坏子线程的阻塞调用并正确处理流和套接字?

3 个答案:

答案 0 :(得分:1)

您还没有提到您的代码正在使用的实际C#网络API调用,但假设它是底层Socket对象上的许多“Receive”方法之一,那么它是正确的,它将无限期地阻塞在一个绑定上连接套接字,除非在Socket对象上设置了超时(ReceiveTimeout)。

设置完成后,如果在该时间内没有收到任何数据,它将返回。然后你可以把一个接收调用放在一个循环上,你可以在外部设置一个布尔值来触发线程停止。

<强>更新

不是在同步读取调用上阻塞线程,而是可以使用DataAvailable在循环中查询NetworkStream以查看是否有任何要读取的内容?

答案 1 :(得分:1)

如何使用异步调用(例如BeginReceive)而不是阻塞调用,并让线程等待对象告诉它干净地终止?创建像ManualResetEvent这样的东西并让线程等待它。从主线程发出事件信号,当侦听线程唤醒时,它可以关闭套接字。

请注意,当使用数据调用回调委托时,如果线程需要接收更多数据,则需要再次调用BeginReceive。在此处查看BeginReceive的说明:http://msdn.microsoft.com/en-us/library/dxkwh6zw

答案 2 :(得分:1)

关闭套接字以进行输入。这将取消阻止读取并使其获得EOS指示,无论API采用何种形式。当你在Windows上时,如果它继续发送,它也会导致另一端得到连接休息。 (此行为取决于平台。)