2013-11-25 93 views
2

看看这个简单的类:线程没有完成

delegate void Log(String message); 
class A { 
    public Log log; 

    ... 

    public void test() { 
    // Empty 
    } 

} 

现在我创建和启动从主界面线程线程并检查它是否结束。

A a = new A(); 
a.log += Log; 

Thread t = new Thread(new ThreadStart(a.test)); 
t.Start(); 

while(true) { 
    System.Threading.Thread.Sleep(200); 
    Console.WriteLine(t.IsAlive); 

} 

通过上面的一切,代码工作正常:

true 
true 
.... 
false 
false 
false 
... 

现在,当我的test方法的代码更改为

public void test() { 
    log("Test"); 
} 

在GUI类的Log方法看起来像这个:

private void Log(String message) 
     { 
      if (this.tb_log.InvokeRequired) 
      { 
       this.tb_log.Invoke((MethodInvoker)delegate() 
       { 
        Log(message); 
       }); 
      } 
      else 
      { 
       // do something with the textbox in the GUI 
      } 
     } 

现在,虽然功能终止我得到以下控制台日志:

true 
true 
true 
true 
true 
true 
... 

线程永远不会终止。你能解释一下吗?

+1

您可以使用'BeginInvoke'来检查问题是否仍然存在? – ChrisK

+0

明显的建议是,它是递归调用自己永远。 – Jeremy

+0

我不确定,只是一个假设 - 您正试图在无限循环中的GUI线程上调用方法。所以你的this.tb_log.Invoke调用永远不会结束 –

回答

2

假设你的while循环发生的GUI线程,你永远不会放弃窗口的控制(因为你是在一个循环中)。你还应该发现你的Invoke从不返回。 (它要求主线程通过在窗口的消息队列中放置消息来执行某些操作,但主线程忙,所以它不会将消息出队)

如果这只是测试代码,则可以使用BeingInvoke ,但实际上,你不应该在你的UI线程中睡觉并在后台线程上检查活动。

取而代之的是,当后台线程通过调用委托完成后通知窗口,或者(更好)使用BackgroundWorker(Winforms)或任务,通过.ContinueWith()调用来通知窗口时它已经完成。