2011-09-01 48 views
0

爲什麼進度條在線程內更改樣式時消失了,以及如何避免發生這種情況?從線程內更改時,ProgressBar消失

我有一個線程運行時間不確定(但可能很長),所以我想使用進度條來跟蹤線程的進度。在開始線程開始之前,我將進度條樣式設置爲選取框,但是一旦線程完成並將進度條樣式設置回塊(您可以通過設置Form.CheckForIllegalCrossThreadCalls = false從另一個線程完成),進度條從消失形式直觀。此外,如果我在窗體上放置了一個按鈕,以便來回更改進度欄樣式,它會重新出現,並且在連續按下按鈕時來回改變樣式。

+0

感謝所有快速答案。我不知道那會很糟糕。當我第一次嘗試這樣做時,msdn說:「你不能從這個線程做到這一點,也許你應該設置Form.CheckForIllegalCrossThreadCalls = false」,所以我做到了,並且這導致了這個 –

+0

某些Msdn文檔可能是一個有點誤導,但這就是像StackOverflow這樣的地方:) –

回答

1

Woah there!遠離CheckForIllegalCrossThreadClass。這個財產,雖然微軟提供它,我敢肯定有非常,非常非常罕見的(我的意思是)使用它,千萬不要碰它。它會直接導致你的軟件受到傷害。

你可以使用一個簡單的ISyncronizeInvoke方法來更新你的UI,which I also wrote a blog post on(非常簡單)。

/// <summary> 
/// Helper class that allows synchronized invoking to be performed in a single line of code. 
/// </summary> 
internal static class SynchronizedInvoke { 
    /// <summary> 
    /// Invokes the specified action on the thread that the specified sync object was created on. 
    /// </summary> 
    public static void Invoke(ISynchronizeInvoke sync, Action action) { 
     if (!sync.InvokeRequired) { 
      action(); 
     } 
     else { 
      object[] args = new object[] { }; 
      sync.Invoke(action, args); 
     } 
    } 
} 

用法很簡單。

private void MyThreadWork() { 
    // Do some work 
    SynchnronizeInvoke.Invoke(uxProgressBar,() => uxProgressBar.Style = ProgressBarStyles.Blocks); 
} 
4

從MSDN言論對CheckForIllegalCrossThreadCalls屬性:

何時 訪問該控件的方法或屬性一個比對照嘗試的創建線程的線程上,它往往會導致 不可預知的結果。一個常見的無效線程活動是調用 訪問控件Handle屬性的錯誤線程。將 CheckForIllegalCrossThreadCalls設置爲true,以便在調試時更容易地找到並診斷此線程活動。

從UI線程以外的線程訪問控件一般被認爲是不好的做法,並且通常不被允許。

您應該改用Control.Invoke方法。我通常處理橫線UI更新這樣的:

public void UpdateProgressBar(int NewValue) 
{ 
    if(InvokeRequired) 
     Invoke(() => UpdateProgressBar(NewValue)); 
    else 
     progressBar.Value = NewValue; 
} 

這在移動辦公到UI線程,其中控制安全訪問。

4

(你可以從另一個線程設置Form.CheckForIllegalCrossThreadCalls做= FALSE)

壞。壞壞壞。 Baaaaaaaad。他們被稱爲非法跨線程電話是有原因的。

您應該更新UI的唯一線程是UI線程。沒有例外。要實現這一點,您應該使用BackgroundWorker並調用ReportProgress方法(並使用ProgressChangedEventHandler來處理它,這將保證在UI線程上執行)。

如果您未使用BackgroundWorker,則可以傳遞一個具有邏輯的委託,以將進度條更新爲進度條上的Invoke方法,以確保代碼正在UI線程上運行。

1

老實說,我從來沒約Form.CheckForIllegalCrossTHreadCalls聽了,但文件說:

當比對照嘗試的創建線程以外的線程 訪問該控件的方法或屬性之一,它往往會導致 不可預知的結果。一個常見的無效線程活動是調用 訪問控件Handle屬性的錯誤線程。

將CheckForIllegalCrossThreadCalls設置爲true可在調試時更容易地找到並診斷此線程活動。

通過將其設置爲false,只需對您提出的問題說「閉嘴」即可。

不能從UI以外的線程更改控制。所以不要使用這個屬性。 只需使用Form的Invoke在主線程上運行代碼即可。

SO Example