3

私の UI では、ボタンを押すと、次のコードが実行されます。

backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
backgroundWorker1.RunWorkerAsync();

これは初めてうまく機能します。ボタンを押すと(無効になります)、バックグラウンドタスクの実行中にウィンドウを移動してクリックすることができます。しかし、バックグラウンド ワーカーが完了して (ボタンが再び有効になり)、もう一度押すと、バックグラウンド ワーカーが実行されますが、ウィンドウを制御できなくなります。

これが2回目に機能しない理由がわかりません。バックグラウンド ワーカーが UI スレッドをブロックしていないことを確認するために、バックグラウンド ワーカーの実行前または実行後に行う必要があることはありますか?

ありがとう!

編集:バックグラウンド ワーカーの ProgressChanged ハンドラーで、プログレス バーと、バックグラウンド ワーカーの進行状況を表示するテキスト ラベルを更新します。それらは常に更新され、フリーズすることはありません。しかし、ウィンドウをドラッグしたり、他のコントロールをクリックしようとすると、定期的にしか反応しません。

バックグラウンド ワーカーは、UI スレッドのグローバル変数であるクラスのインスタンスにアクセスします。オブジェクトをインスタンス化し、バックグラウンド ワーカーの DoWork 内からオブジェクトが実行する長い関数を実行し、バックグラウンド ワーカーが終了した後にオブジェクトにアクセスして結果を表示するというアイデアでした。これは大丈夫ですか?

バックグラウンド ワーカーの DoWork で呼び出されるこのオブジェクトの関数内で、いくつかの静的クラスにアクセスします。これにより、何らかのスレッドの問題が発生しますか?

4

2 に答える 2

3

は 2 つの方法で使用できBackgroundWorkerます。

  1. ツールボックスからフォームにドロップし、プロパティ ウィンドウでプロパティとイベントを設定します。

  2. プログラムで定義する。

おそらく、両方のアプローチを混在させました。


最初のアプローチを使用した場合は、すべての初期化コードを削除して (フォームが自動的に実行します!)、呼び出しのみを行います。

backgroundWorker1.RunWorkerAsync();

2 番目の方法を使用する場合は、フォームに配置しないでください。代わりに、メンバー変数として宣言します。コンポーネントとしてフォームに追加できる唯一の目的は、プロパティ ウィンドウからプロパティとイベントを設定できるようにすることです。はBackgroundWorkerフォームから何も必要とせず、どのフォームからも完全に独立して使用できます。次に、フォームコンストラクターでワーカーをセットアップします

backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerSupportsCancellation = true;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.ProgressChanged +=
    new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
backgroundWorker1.RunWorkerCompleted +=
    new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

ボタンクリックハンドラーでこれだけを行います

backgroundWorker1.RunWorkerAsync();

このセクションのツールボックスにあるほとんどまたはすべてのコンポーネントについて、同じ考慮事項が当てはまりますComponents

于 2012-06-14T18:08:47.780 に答える
0

可能であれば、リアクティブ拡張機能を使用してみてください...非同期処理に最適です。

于 2012-06-14T18:16:50.570 に答える