2011-11-27 36 views
4

我创建一个TCP连接的服务器。 TCP连接在其自己的线程中运行无限期的时间。有没有一种很好的模式来允许安全关闭TcpListener和Client以及线程?以下是我到目前为止。正确的方法来中止一个封锁线程

private volatile bool Shudown; 

void ThreadStart1() 
{ 
    TcpListener listener = null; 
    TcpClient client = null; 
    Stream s = null; 
    try 
    { 
     listener = new TcpListener(60000); 
     client = listener.AcceptTcpClient(); 
     Stream s = client.GetStrea(); 
     while(!Shutdown) // use shutdown to gracefully shutdown thread. 
     { 
      try 
      { 
       string msg = s.ReadLine(); // This blocks the thread so setting shutdown = true will never occur unless a client sends a message. 
       DoSomething(msg); 
      } 
      catch(IOException ex){ } // I would like to avoid using Exceptions for flow control 
      catch(Exception ex) { throw; } 
     } 
    } 
    catch(Exception ex) 
    { 
     LogException(ex); 
     throw ex; 
    } 
    finally 
    { 
     if(listener != null) listener.Close(); 
     if(s != null) s.Close(); 
     if(client != null) client.Close(); 
    } 
} 
+0

你的catch子句是多余的。这不是你的问题的解决方案,但它仍然是多余的。 – zmbq

+0

你的权利。我编辑表明我的真实意图。 – Neal

+3

在类似的说明中,你不应该这么做,因为这会重置你的堆栈跟踪。尝试使用'throw'代替。请参阅:http://stackoverflow.com/questions/178456/what-is-the-proper-way-to-re-throw-an-exception-in-c –

回答

2

有没有一种好的模式来允许安全关闭线程?

更改while循环如下:

​​

检查这个MSDN example了解详情。 将中断布尔值设置为true将使线程在检查while条件时脱离循环。

是否有良好的模式允许安全关闭TcpListener和 客户端?

为避免重复,请检查该SO question

至于如何终止ReadLine();一个阻塞线程以下listener.Server.Close();应该做的工作,并从阻塞调用回到你的问题。

+0

这是安全线程关闭的注释模式。但是这并不能解决问题。如何通过Stream.ReadLine()阻止它被中断的线程?我会更新问题以显示我在说什么。 – Neal

+1

来自另一个线程的listener.Server.Close()将打破ReadLine阻塞调用。 – GETah

+0

真的吗?我没有考虑尝试。我会看看是否有效。如果这适用于我所需要的,您可以创建一个答案,我将接受它作为解决方案。 – Neal

5

在NetworkStream上设置超时(client.ReadTimeout = ...)。一旦读取操作超时,检查主线程是否表示您停止(通过设置变量或AutoResetEvent)。如果信号停止,请优雅地退出。如果不是,请再次尝试阅读,直到下一次超时。

设置一个0.5或1秒的超时时间就足够了 - 你将能够及时退出线程,而且在CPU上很容易。

+0

打我吧,这也是我的解决方案,只是赶上例外,确保它是一个超时错误(如果它是其他东西扔它),并继续循环,如果变量仍然是false – Ben

+0

这将抛出一个例外。我如何处理,而不会失去连接?如果有一个超时选项没有抛出连接,而是返回一个null或某些值以允许以给定间隔解锁线程,那将会很好。 – Neal

+0

关闭异常时连接未关闭。赶上IOException,确保它是一个超时(查看HRESULT),并保持循环读取。 – zmbq

1

或许不是同步调用NetworkStream对象上的Read,而应该使用BeginRead和EndRead异步执行它,并在完成后调用NetworkStream上的Close()。