処理中にWindowsフォームアプリケーションのラベルを更新する最良の方法は何ですか?
ユーザーがボタンをクリックしたときに、ユーザーのシステム上のファイルを処理するループがあります。
foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
// Do processing
// Show progress bar
// Update Label on Form, "f.Name is done processing, now processing..."
}
サンプルコードは何ですか?
これは正確に何と呼ばれていますか?それはスレッドですか、デリゲートですか?
簡単な修正方法は次のとおりです。
Label1.Text = f.Name + " is done processing, now processing...";
Label1.Refresh();
本当にDoEvents
を避けたいのです。そうしないと、ユーザーがフォームのボタンを繰り返し押した場合に問題が発生します。
あるスレッドから別のスレッドにデータを取得する必要があります。これはいくつかの方法で行うことができます...
最初に、「バックグラウンド」スレッドは、何らかの種類の「CurrentStatus」文字列変数を更新します。次に、フォームにタイマーを設定し、CurrentStatus変数を取得して、ラベルを更新します。
次に、ラベルコントロールのInvokeRequiredプロパティを使用して、デリゲートを使用して、バックグラウンドスレッドからUIスレッドへの操作を単純に呼び出すことができます。例えば...
private delegate void UpdateStatusDelegate(string status);
private void UpdateStatus(string status)
{
if (this.label1.InvokeRequired)
{
this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status });
return;
}
this.label1.Text = status;
}
UpdateStatus()メソッドは任意のスレッド(UIまたはバックグラウンド)から呼び出すことができ、メインUIスレッドで操作を呼び出す必要があるかどうかを検出します(必要な場合は呼び出します)。
スレッドを実際にセットアップするには、次のようにします。
private void StartProcessing()
{
System.Threading.Thread procThread = new System.Threading.Thread(this.Process);
procThread.Start();
}
private void Process() // This is the actual method of the thread
{
foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
// Do processing
// Show progress bar
// Update Label on Form, "f.Name is done processing, now processing..."
UpdateStatus("Processing " + f.Name + "...");
}
}
次に、ユーザーが「GO」ボタンをクリックすると、単にStartProcessing()が呼び出されます。
あなたは別のスレッドでこれを実行し、そのスレッドからUIスレッドを更新する必要があります。 UIスレッドでこの作業を実行することにより、さらに処理をブロックしています。
このコードをUIスレッドに移動できない場合は、常に Application.DoEvents
、しかし私は強くこれらのオプションを最初に検討することをお勧めします:
処理が長い場合は、バックグラウンドワーカースレッドで実行します。
http://msdn.Microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
私も使用することをお勧めします:
Application.DoEvents();
現在メッセージキューにあるすべてのWindowsメッセージを処理します。