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

C# 如何关闭包含对NetworkStream.Read的阻塞调用的线程,c#,.net,multithreading,sockets,C#,.net,Multithreading,Sockets,我正在浏览一些不是我自己编写的代码,我试图了解是什么导致应用程序崩溃 我认为这可能归结于它如何处理资源和管理线程 主父线程创建一个新的应用层客户机(TCPMonitor),然后该客户机创建另一个处理TCP套接字通信的类(TCPListen)。该类生成一个新的线程循环,该循环创建一个新的TCP套接字客户端、该套接字上的读取网络流,然后调用一个同步阻塞读取() 但是,如果发生网络错误连接,则会在TCPListen线程循环中捕获异常,并将事件发回所属类TCPMonitor。TCPMonitor然后检查

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

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

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

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


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

您没有提到代码正在使用的实际C#network API调用,但假设它是众多“接收”调用之一方法,除非在套接字对象上设置了超时(),否则它将无限期地在绑定连接的套接字上阻塞,这是正确的

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

更新:


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

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


请注意,当使用数据调用回调委托时,如果线程需要接收更多数据,则需要再次调用
BeginReceive
。检查此处的
BeginReceive
说明:

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

我认为如果存在循环且catch块重新抛出异常但未退出循环,则
TCPListen
仍将在
Read
中被阻止。是这样吗?在读取完成后,套接字和流上的close方法周围有try/catch块,但它们不是rethrown。循环中的大多数代码也有更广泛的try/catch,这也会吞下错误。这将向父级引发一个事件,然后父级将处理thread类。该调用是一个简单的NetworkStream.Read()。如果读取超时不确定(-1)或设置为5分钟(300000),则线程将挂起读取。但是,如果对thread类本身调用dispose,实际的线程循环会发生什么情况?如果在VS中运行调试构建,它将继续阻塞,我希望看到它继续显示为“正在运行”,即使程序似乎已经停止。我猜发布版本会破坏线程和套接字连接,但不会特别优雅。