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



我正在查看一些不是自己编写的代码,并试图了解是什么导致应用程序崩溃。

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

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

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

此时TCPListen Read()肯定仍将处于阻塞调用中?如果是这种情况,我如何确保从父线程调用Dispose将使子线程脱离阻塞调用,并正确地处理流和套接字?

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

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

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

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

一旦设置,如果在该时间内没有收到任何数据,它将返回。然后,您可以将Receieve调用放在某个布尔值的循环中,您可以在外部设置该布尔值以触发线程停止。

更新:

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

最新更新