2014-01-08 94 views
0

當我啓動主線程時,我也啓動了第二個線程,但第二個線程仍然等待主線程。我期望當我開始一個新的線程時,它會在沒有連接到主線程的情況下工作。那麼爲什麼panel1在主線程完成其工作之後變得可見?如果第二個線程等待主線程

private void comboBox1_SelectedIndexChanged_1(object sender, EventArgs e) 
    { 
     Thread thread = new Thread(new ThreadStart(threadUI)); 
     thread.Start(); 

     // This class is loading something from the server on the main thread 
     excel.get_data_from_excel(comboBox1.SelectedItem.ToString(), this); 
    } 
    private void threadUI() 
    { 
     if (panel1.InvokeRequired) 
     { 
      panel1.Invoke(new newDelegate(threadUI)); 
     } 
     else 
     { 
      panel1.Visible = true; 
     } 
    } 

回答

5

Invoke方法將不會返回,直到主線程執行委託。如果您希望後臺線程在不等待主線程的情況下繼續,請改爲使用BeginInvoke

但是,請注意,主線程上只能發生一件事。您可以調用Invoke或BeginInvoke,但在主線程閒置之前不會處理委託。也就是說,如果get_data_from_excel需要很長時間,則在get_data_from_excel完成之前,panel1.Visible=true纔會生效,comboBox1_SelectedIndexChanged_1返回,並且主線程變爲空閒狀態。

如果你真的想讓這些東西「並行」,你必須在後臺線程中執行get_data_from_excel。

+0

我將那行改成這樣:PANEL1。BeginInvoke(new newDelegate(threadUI)); //但它仍在等待mainThread變爲可見 – Toprak

+3

這不會幫助他解決他的問題。如果沒有通過使用'BeginInvoke'阻止第二個線程將會修改問題的一個症狀而不解決根本問題。 – Servy

+1

查看我的編輯。我認爲你有比Invoke/BeginInvoke更大的問題。 –

1

您正在UI線程中長時間運行非UI工作。

你創建的第二個線程除了調用Invoke並且做了一些工作之外什麼都不做。什麼Invoke確實在UI線程中運行了一些代碼,目前它正忙於做一些非UI工作。它不會計劃在該工作完成之後運行。

你應該做的是在另一個線程中做非常長的非UI工作,而不是UI線程。

0

看起來你對Invoke()感到困惑。

Invoke()用於排隊顯示panel1的線程的委託。但是,Invoke()塊UNTIL委託已運行完成。因此,您的第二個線程阻止在Invoke()

如果您希望在主線程上運行一個動作,同時從第二個線程調用它而不阻止 ...然後使用BeginInvoke()。它會排隊委託,然後立即返回。

Servy的評論

Servy帶來了一個好點。第二個線程的意義是什麼,如果它只是立即調用第一個線程?如果您要立即調整控件的屬性,則不需要創建第二個線程。

但它看起來像你從Excel中抓取數據。該代碼段應該在第二個線程中,然後輸出使用BeginInvoke()

+0

這不會幫助他解決他的問題。如果沒有通過使用'BeginInvoke'阻止第二個線程將會修改問題的一個症狀而不解決根本問題。 – Servy

+0

@Servy你是對的。我調整了答案。 – Andrew

0

如果我使用的代碼就這樣它也在等待下一個完整的行 完成其工作

private void comboBox1_SelectedIndexChanged_1(object sender, EventArgs e) 
{ 
    panel1.Visible = true; 
    excel.get_data_from_excel(comboBox1.SelectedItem.ToString(), this); 
} 
+0

我現在這是一個強化問題,但我也是新的C#,並試圖找出它 – Toprak

+0

在這裏,你仍然阻塞UI線程,所以面板的可見性將不會改變,直到操作完成後。 – Servy