2010-11-09 250 views
1

我有一个包含form1和program.cs文件的winform应用程序。在program.cs中我初始化form1,除此之外,我有一台服务器。我的问题是:当我关闭表单时,如何停止线程?这里是我的Program.cs文件的一部分:停止线程

public void start() 
     { 
      this.tcpListener = new TcpListener(IPAddress.Any, 3000); 
      this.listenThread = new Thread(new ThreadStart(ListenForClients)); 
      this.listenThread.Start(); 
     } 


     private void ListenForClients() 
     { 
      //MessageBox.Show("in thread"); 
      this.tcpListener.Start(); 

      while (true) 
      { 
       //blocks until a client has connected to the server 
       TcpClient client = this.tcpListener.AcceptTcpClient(); 

       //create a thread to handle communication 
       //with connected client 
       sThread a = new sThread(form1, listaThreads); 
       listaThreads.Add(a); 
       Thread clientThread = new Thread(new ParameterizedThreadStart(a.HandleClientComm)); 
       clientThread.Start(client); 
      } 
     } 

回答

3

您可以从另一个线索调用TcpListenerClose()

TcpListener.Close()将简单地调用Socket.Close()并且这是线程安全的。

我不确定AcceptTcpClient如何反应,但您必须检查。至少它会以正常的方式停止你的监听线程。

所以,你这样做:

tcpListener.Close(); 
listenThread.Join(); 

这将很好地关闭线程。

+0

tcpListener.Close();不存在。我发现tcpListener.Close(); AcceptTcpClient给出以下错误:阻塞操作被WSACancelBlockingCall调用中断 – Alex 2010-11-09 09:23:23

+1

我相信'WSACancelBlockingCall'是在这里终止阻塞调用的正确方法。您应该将该异常视为关闭该线程的触发器。我首先要用'BeginAcceptTcpClient'回答,但这是您在不使用异步版本的调用时终止线程的方式。 – 2010-11-09 09:30:12

+0

我解决了它:使用此代码:尝试 { client = this.tcpListener。AcceptTcpClient(); } catch { break; } – Alex 2010-11-09 10:35:10

3

而不是主动放弃他们,你应该发信号给他们,他们应该停止,让他们停止在自己的时间。如果您使用任何BackgroundWorker s,则可以使用CancelAsync方法。对于像在你的例子中手动创建的线程,你可以使用线程必须偶尔检查的布尔标志(使用适当的同步)。当你的程序即将关闭设置标志。避免在线程中调用阻塞方法 - 使用异步方法而不是AcceptTcpClient而不是BeginAcceptTcpClient

如果您正在使用(或可以升级到).NET 4,那么您还应该考虑使用Task Parallel Library,其中任务为cancellable

+0

他没有使用BG工作者 – 2010-11-09 08:29:17

+0

@Liviu M .:你怎么知道的?他没有发布他的所有代码。 – 2010-11-09 08:30:09

+0

我认为现有的代码相当明显:)也许Alexnadru可以证实它。 – 2010-11-09 08:32:02

0

在运行异步的方法中,您应该检查一个布尔标志,如cancel,当您想要停止线程时,您从外部设置为true。

public bool cancel = false; 

public void MethodRuningOnThread() 
{ 
    while(!cancel) 
    { 
     //do stuff 
    } 
} 

建议不要使用Thread.Abort()方法。

+0

我同意你的看法,但是我担心在我改变那个标志之前,我的程序会被阻塞在sr.readLine()中。 – Alex 2010-11-09 09:25:19