私はいくつかの調査を行いましたが、C#のワーカースレッドからフォームコントロールを更新するための好ましい方法を実際に見つけることができません。BackgroundWorkerコンポーネントについて知っていますが、BackgroundWorkerコンポーネントを使用せずにそれを行うための最良の方法は何ですか?
4 に答える
UIスレッド自体以外のスレッドからUIを更新しないという一般的な経験則があります。BackgroundWorkerの機能を使用することをお勧めしますが、使用したくなく、別のスレッドで何かが発生している場合は、「Invoke」またはBeginInvokeを実行して、デリゲートにUIスレッドでメソッドを実行させる必要があります。
編集:ジョンBはコメントでこの良い点を述べました:
Invoke()は同期であり、BeginInvoke()は非同期であることに注意してください。Invoke()を使用する場合は、デッドロックを引き起こさないように注意する必要があります。呼び出しを同期させる必要が本当にない限り、BeginInvoke()をお勧めします。
いくつかの簡単なサンプルコード:
// Updates the textbox text.
private void UpdateText(string text)
{
// Set the textbox text.
m_TextBox.Text = text;
}
public delegate void UpdateTextCallback(string text);
// Then from your thread you can call this...
m_TextBox.Invoke(new UpdateTextCallback(this.UpdateText),
new object[]{"Text generated on non-UI thread."});
なぜBackgroundWorkerを使用してそれを実行したくないのですか?ProgressChangedと呼ばれる素晴らしいコールバックイベントがあり、UIスレッドに更新について通知し、進行中のバータイプの更新などに最適です。
Invoke を呼び出すときは、InvokeRequired (VS2008 のみ) も検討します。別のスレッドから UI を更新しない場合があります。デリゲートなどを作成するオーバーヘッドを節約します。
if (InvokeRequired)
{
//This.Invoke added to circumvent cross threading exceptions.
this.Invoke(new UpdateProgressBarHandler(UpdateProgressBar), new object[] { progressPercentage });
}
else
{
UpdateProgressBar(progressPercentage);
}