小さな.NET(Windows Forms)アプリケーションを作成していますが、マルチスレッド化の権利を得ることができません。処理中にコントロールの更新を処理する方法は?
アプリケーションには非常に単純なロジックがあります。入力するパラメータ、処理を開始するボタン、および進行状況バーが表示されたメインフォームが表示されます。ユーザーがボタンをクリックすると処理が開始され、プログラムの実行中にプログレスバーが更新されます。警告/情報を表示するために処理中にMessageBox
がポップアップし、処理が終了するとMessageBox
が結果をポップアップします。かなり単純です...しかし、コントロールのアップデートを正しく処理する方法を見つけることができないようです。
まず、私はButton_Clickedイベントですべての処理を行います。これはうまくいかなかった:それは働いたが、フォームは処理中に完全に反応しなくなり、ユーザーのクリックについて全く気にしなかった。私はこれが実際にイベントを処理するために忙しかったので、他のプロセスの処理を停止していたと仮定していたので、私はマルチスレッド化に行きました。
ボタン処理イベントで私は新しいThread
を開始し、処理を行い、その後Thread.Join
を呼び出しました。 MSDNドキュメントでは、Thread.Join
について: "スレッドとCOMとSendMessageのポンピングを続行しながらスレッドを終了するまで呼び出しスレッドをブロックする"(http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx)しかし、これはそうではないようです。Thread.Join
を呼び出した後、スレッドが終了するまで、フォームは再び応答しなくなりました。どうしてこれなの?私はJoinアイデアを捨ててすぐにイベントハンドリング機能から戻ってきました(ユーザーが同時に複数の処理を開始しないようにフォームのボタンを無効にします)が、別の問題が発生しました。実行時に、所有者ではないスレッドからコントロールを呼び出したことに不満がありました。
だから私は最終的にBackgroundWorker
と一緒に行った:私は、フォームに1を追加し、そのRunWorkerAsync()
メソッドと呼ばれ、(クロススレッド制御更新の問題を回避するため)ProgressChanged
イベントを発生し、メインフォームでそれを処理するためにReportProgress()
を使用。私は最終的にプログレスバーを更新することができました...しかし、これは完全に非同期です:ワーカースレッドがReportProgress()
(1秒でさえ)を呼び出した後、プログレスバーは実際には何らかのランダムな間隔で更新され、 。二つの例は:私は、現在の処理ステップに関するいくつかのメッセージを表示するには、ワーカースレッドからReportProgress()
、その後MessageBox.Show()
を呼び出す場合
- 、私はメッセージボックスがポップアップ表示さ後を進めるプログレスバーを見ることができます。
- 私は結果を最後に
MessageBox
をポップアップさせるRunWorkerCompleted
イベントがあります。プログレスバーが最後のステップをまだ満たしている間に、画面にポップアップが表示されます。
私はここで何が欠けていますか?
あなたは何も見逃してしまったようです。メッセージボックスは必要ですか?あなたがそれを取り除くと、それも醜さを減少させるのでしょうか? – Kangkan
はい、アプリケーションロジックは、処理中でも終了時でもそれらを要求します。もちろん、そこに 'Thread.Sleep()'を置くこともできますが、これは本当に醜いハックのように見えます... – Massimo