4

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

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

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

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

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

4

3 回答 3

1

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

请注意,当使用数据调用回调委托时,BeginReceive如果线程需要接收更多数据,则需要进行另一次调用。检查这里的描述:http BeginReceive: //msdn.microsoft.com/en-us/library/dxkwh6zw

于 2012-09-12T10:13:36.070 回答
1

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

于 2012-09-14T22:30:19.767 回答
1

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

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

更新:

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

于 2012-09-12T09:45:52.653 回答