バックグラウンドワーカースレッドを使用すると、マルチスレッドの作業が楽になりますか?
はい、とてもそうです。これは、ワーカースレッドからUIを更新できないという事実に対処するのに役立ちます。特に、ProgressChangedイベントを使用すると進行状況を表示でき、RunWorkerCompletedイベントを使用すると、クロススレッドの問題に対処することなく、ワーカースレッドの結果を使用してUIを更新できます。
なぜe->Resultが必要なのですか?
行った作業の結果をUIスレッドに戻すため。RunWorkerCompletedイベントハンドラーのe->Resultプロパティで値を取得します。次に、その結果でUIを更新します。
関数に渡される引数は何ですか?
ワーカースレッドに何をすべきかを指示するために、それはオプションです。それ以外の点では、引数を任意のメソッドに渡すのと同じですが、引数を選択できないため、さらに厄介です。通常、UIからある種の値を渡します。たとえば、複数の値を渡す必要がある場合は、小さなヘルパークラスを使用します。ワーカーでUI値を取得しようとするよりも、常にこれを優先します。これは非常に面倒です。
CPUHungryFunction()で何をすべきですか?
もちろんCPUサイクルを焼きます。または、一般に、dbaseクエリのように、時間がかかることを行います。これはCPUサイクルを消費しませんが、結果を待っている間にUIスレッドが停止するのに時間がかかりすぎます。大まかに言って、1秒以上かかることを行う必要がある場合は、UIスレッドではなくワーカースレッドで実行する必要があります。
CPUHungryFunction()に無期限にループするwhileループがある場合はどうなりますか?
そうすれば、あなたの労働者は決して完了せず、結果を生み出すこともありません。これは便利かもしれませんが、一般的ではありません。通常、これにはBGWを使用せず、IsBackgroundプロパティがtrueに設定されている通常のスレッドのみを使用します。
ワーカースレッドが取得するプロセッサ時間を制御できますか?
Thread.Sleep()を呼び出して、人為的に速度を落とすことで、いくつかの問題が発生します。これは一般的なことではありません。ワーカースレッドを開始するポイントは、作業を行うことです。スリープ状態のスレッドは、非生産的な方法で高価なリソースを使用しています。
設定された期間内にループがループする回数をより具体的に制御できますか?1秒間に30回ループするだけでよいのに、1秒間に1000回ループするCPUを使い果たしたくありません。
上記と同じように、あなたは眠らなければならないでしょう。これを行うには、ループを30回実行してから、1秒間スリープします。
GUIの更新速度を制御する必要がありますか?
はい、それは非常に重要です。ReportProgress()は、1秒間に何千ものUI更新を生成する消防ホースになる可能性があります。UIスレッドがそのレートに追いつかない場合、これで簡単に問題が発生する可能性があります。UIスレッドは、UIのペイントや入力への応答など、通常の業務を停止します。ProgressChangedイベントハンドラーを実行するために別のinvoke要求を処理し続ける必要があるためです。副作用は、UIがフリーズしているように見えることです。これにより、ワーカーで解決しようとしていた正確な問題が発生します。実際にはフリーズしていません。そのように見えますが、まだイベントハンドラーを実行しています。ただし、ユーザーには違いはわかりません。
覚えておくべきことの1つは、ReportProgress()は人間の目を幸せに保つだけでよいということです。1秒間に20回を超える頻度で発生する更新を確認することはできません。それを超えると、それはただ読めないぼやけに変わります。したがって、とにかく役に立たないUIの更新に時間を無駄にしないでください。また、消火ホースの問題も自動的に回避されます。更新レートの調整はプログラムする必要があり、BGWには組み込まれていません。