web-dev-qa-db-ja.com

WPFBackgroundWorkerとディスパッチャー

私のWPFアプリケーションでは、非同期操作を実行してから、GUIを更新する必要があります。そして、このことは、私がさまざまな操作でさまざまな瞬間に何度もしなければなりません。これを行うには、DispatcherとBackgroundWorkerの2つの方法を知っています。

私が選ぶとき、私が戻るのは難しいので、私はあなたに尋ねます:何が良いですか?どちらか一方を選択する理由は何ですか?

ありがとうございました!ピレッギ

32
lamarmora

Dispatcherと他のスレッド化方法の主な違いは、Dispatcherが実際にはマルチスレッド化されていないことです。ディスパッチャは、適切に機能するために単一のスレッドを必要とするコントロールを管理します。 DispatcherのBeginInvokeメソッドは、後で実行するためにイベントをキューに入れます(優先度などに応じて)が、同じスレッド上にあります。

一方、BackgroundWorkerは、実際には、コードが呼び出されると同時に、別のスレッドでコードを実行します。また、コントロールとメッセージキューを担当するアプリケーションのメインスレッド(WPFの場合はディスパッチャースレッドとWPFの場合はディスパッチャースレッド)と自動的に同期するため(少なくともこれは正しく覚えていると思います)、真のスレッドよりも使いやすくなっています。 Silverlight)であるため、バックグラウンドスレッドからコントロールを更新するときにDispatcher.Invoke(またはWinFormsではControl.Invoke)を使用する必要はありませんが、常に推奨されるとは限りません。

リードが言ったように、タスク並列ライブラリは素晴らしい代替オプションです。

編集:さらなる観察。

上で述べたように、ディスパッチャは実際にはマルチスレッドではありません。それはあなたが別の時にそれに渡すデリゲートを実行するので、それはそれの幻想を与えるだけです。ディスパッチャーを使用するのは、コードが実際にアプリケーションの表示の側面(つまり、コントロール、ページ、ウィンドウなど)のみを処理する場合のみです。そしてもちろん、その主な用途は、実際にはotherスレッドからアクションをトリガーして、コントロールを正しくまたは適切なタイミングで更新することです(たとえば、一部のコントロールがレンダリング/配置された後にのみフォーカスを設定します- WPFではレンダリングが正確に決定論的ではないため、ディスパッチャを使用して完全に実行するのが最も簡単です。

BackgroundWorkerは、マルチスレッドコードを通常よりもはるかに簡単にすることができます。理解するのは簡単な概念であり、何よりも(意味がある場合は)カスタムワーカーを派生させることができます。カスタムワーカーは、パラメーター、進行状況の通知、キャンセルなどとして機能できるプロパティを備えた、単一のタスクを非同期で実行する特殊なクラスです。 。私は常にBackgroundWorkerが大きな助けになると感じました(ローカリゼーションを適切に維持するために元のスレッドのカルチャを維持するためにBackgroundWorkerから派生する必要がある場合を除く)

最も強力ですが、難しいパスは、利用可能な最低レベルのSystem.Threading.Threadを使用することです。ただし、物事を間違えるのは簡単なので、あまりお勧めできません。マルチスレッドプログラミングはhardであり、それは当然のことです。ただし、すべての側面を理解したい場合は、多くの優れた情報があります。 この優れた記事 私たちの良き仲間であるJon Skeetがすぐに頭に浮かびます(記事の最後のページにもかなりの数があります)非常に興味深いリンクの)。

.Net 4.0には、別のオプションであるタスク並列ライブラリがあります。私はまだそれをあまり使っていませんが、私が見たところ、それは印象的です(そしてPLINQは単に素晴らしいです)。あなたがそれを学ぶための好奇心とリソースを持っているなら、それは私がお勧めするものです(結局のところ、それはそれ多くを学ぶ必要はありません)。

38
Alex Paven

BackgroundWorkerは、進行状況の通知と完了イベントを提供する単一の操作を実行している場合に最適です。ただし、同じ操作を複数回、または複数の操作を実行する場合は、複数のBackgroundWorkerが必要になります。この場合、面倒になる可能性があります。

進行状況イベントが必要ない場合は、ThreadPoolとDispatcherの使用が簡単になります。特に、かなりの数の異なる操作を実行する場合はそうです。

ただし、C#4がオプションである場合は、タスク並列ライブラリを使用することも優れたオプションです。これにより、現在のSynchronizationContextを使用してセットアップされた継続タスクを使用できます。これにより、多くの場合、はるかに単純でクリーンなモデルが提供されます。詳細については、件名について 私のブログ投稿 を参照してください。

8
Reed Copsey