2011-10-05 29 views
0

我最近一直在處理一個應用程序,我想通過StatusBar控件中包含的ToolStripProgressBar控件在狀態欄中顯示另一個線程的進度。在我試圖添加這段代碼之前,我原本的代碼改變了ToolStripStatusLabel控件的文本,爲此我使用了委託的Invoke方法,並且一切正常。但是,我發現當我嘗試使用ToolStripProgressBar時,狀態欄的Invoke方法調用失敗,沒有通知(沒有錯誤,沒有例外,沒有任何提示)。自從我學到了以後,我要用一個BackgroundWorker控件來使用進度條。所以我的代碼工作,但我不明白爲什麼我不能使用已經似乎工作的Invoke方法。爲什麼StatusBar.Invoke方法不適用於ToolStripProgressBar?

的什麼工作,什麼都沒有的一些例子:

這個工作

public delegate void changeStatusMessage(String message); 
public changeStatusMessage changeStatusMessageDelegate; 
public void changeStatusMessageMethod(String message){ 
     if(statusbar.InvokeRequired){ 
      statusbar.Invoke(changeStatusMessageDelegate, new Object[] {message}); 
     }else{ 
      toolstripLabel.Text = message; 
     } 
} 

這不起作用

public delegate void incrementProgressBar(int value); 
public incrementProgressBar incrementProgressBarDelegate; 
public void incrementProgressBarMethod(int value){ 
     if(statusbar.InvokeRequired){ 
      statusbar.Invoke(incrementProgressBarDelegate, new Object[] {value}); 
     }else{ 
      toolstripProgress.Increment(value); 
     } 
} 

在這個例子中,沒有工作的InvokeRequired財產是真的,所以Invoke方法被調用,然後沒有任何反應。正如我預計它再次調用incrementProgressBarMethod,這裏InvokeRequired是錯誤的,因此允許Increment方法觸發。

我真的很想知道爲什麼這不起作用。正如我所說我已經重新使用BackgroundWorker,我只想要一個解釋。

+1

沒有什麼特殊的地方TSPB會交給你一個簡單的解釋。如果主線程被阻塞,Control.Invoke()往往容易死鎖,所以「沒有任何事情發生」並不罕見。堅持BackgroundWorker。 –

+0

我從來沒有說過我想要一個「簡單」的解釋,複雜的解釋也會起作用。簡單地告訴我,Control.Invoke()可能導致死鎖並不足以讓我理解原因。 Control.Invoke()提供了一個原因,爲什麼我不能將它用於這一個控件,當用相同的代碼以類似的方式處理控件時沒有問題。 – JRSofty

+0

顯示問題的任何人都可以測試,並且您會得到您的答案的過帳代碼。 –

回答

0

調用postmessage API並在windows消息中排隊消息。如果UI線程被阻塞,那麼你可能會發生死鎖,因爲它不能推送排隊的消息,什麼都不會發生。所需調用的另一方不被解僱,如果有什麼東西在等待它,砰,死鎖。

這就是您需要小心Invoke的原因。

How to invoke a function on parent thread in .NET?

但你的問題是創建委託的,它是一個空的代表,你需要創建在同一個線程,它是由調用調用這個代表,因爲其他的方式,下屬系統會編組失敗(它是一個指針)。

private void changeStatusMessageMethod(String message) 
    { 
     if (this.InvokeRequired) 
     { 
      var changeStatusMessageDelegate = new changeStatusMessage(changeStatusMessageMethod); 
      this.Invoke(changeStatusMessageDelegate, new Object[] { message }); 
     } 
     else 
     { 
      toolstripLabel.Text = message; 
     } 
    } 
    delegate void incrementProgressBar(int value); 
    private void incrementProgressBarMethod(int value) 
    { 
     if (this.InvokeRequired) 
     { 
      var incrementProgressBarDelegate = new incrementProgressBar(incrementProgressBarMethod); 
      this.Invoke(incrementProgressBarDelegate, new Object[] { value }); 
     } 
     else 
     { 
      toolstripProgress.Increment(value); 
     } 
    } 

這部作品的dotnet框架V4

private void button1_Click(object sender, EventArgs e) 
    { 
     var t = new System.Threading.Thread(new System.Threading.ThreadStart(x)); 
     t.Start(); 
    } 

    private void x() 
    { 
     do 
     { 
      changeStatusMessageMethod(DateTime.Now.ToString()); 
      System.Threading.Thread.Sleep(1000); 
     } while (true); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     var t = new System.Threading.Thread(new System.Threading.ThreadStart(y)); 
     t.Start(); 
    } 

    private void y() 
    { 
     do 
     { 
      incrementProgressBarMethod(1); 
      System.Threading.Thread.Sleep(1000); 
     } while (true); 
    } 
相關問題