2013-11-25 147 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()調用來通知窗口時它已經完成。