2010-02-02 57 views
5

我使用5個BackgroundWorker對象在同一時間爲特定目的而運行,並且它們都必須更改相同的標籤。我怎麼做?BackgroundWorker多線程訪問表單

如何從多個線程修改表單呢?如果我想更改公共字符串,我該如何做?

回答

17

使用Control.Invoke與委託。

而不是說

label4.Text = "Hello"; 

在你的後臺工作線程,說

label4.Invoke(new Action(() => 
{ 
    label4.Text = "Hello"; 
} 
)); 

一切內部{}執行控制的線程上,這樣你就避免了異常。

這使您可以從BackgroundWorker對用戶界面進行任意更改,而不僅僅報告進度。

+0

ReportProgress還可以讓你對UI進行任意更改。 –

+0

如果現在發生在我的表單的公共字符串中,我該如何調用它? – Marcelo

+0

@亨克:ReportProgress將只允許BackroundWorker發送一個單一的「UserState」對象,該對象必須由ProgressChanged事件處理程序解釋才能實際更新UI。我想說的是,使用Invoke()方法,您可以將更新的代碼放在首先創建BackgroundWorker的方法中,從而提高代碼的效率和可讀性。當然,這是一個設計決定,具有所有正常的折衷。 – RobC

2

您可以在BackgroundWorker中使用ReportProgress方法更改標籤,並在ProgressChanged事件處理函數中編寫實際代碼。

+0

問題在於這是一個顯示標籤的異常,所以不是每次由後臺工作人員運行的方法都會與表單進行任何交互。 – Marcelo

+0

您可以使用RaYell的建議將信息發佈到GUI,然後可以自行更新。 –

0

看看this answer。如果你有一個,五個或千個工作者線程(在概念上),這並不重要。

1

您應該非常謹慎地調用同步Invoke而不是gui上的異步BeginInvoke。你很快就會有一個反應遲鈍的gui,似乎正在努力繪製自己,以及潛在的僵局。
這取決於你更新它的頻率 - 你的後臺線程是否真的需要等待gui返回?這聽起來像是你的模型有問題。

1

以及Control.BeginInvoke,你可以看看SynchronizationContext

當您創建BackgroundWorkers時,假設您正在從UI線程創建它們,則將SynchronizationContext.Current傳遞給工作人員。當BackgroundWorkers準備在UI線程上返回一些東西時,它們會在創建SynchronizationContext實例時調用SynchronizationContext實例上的Synchronization.Post方法。

SynchronizationContext herehere上有兩篇很好的文章。