指定された間隔の後に WCF サービスを呼び出し、サービスから受信したデータに従って出力を表示する Windows フォーム アプリケーションを開発しています。この目的のために、500ミリ秒後にそのWCFサービスメソッドを呼び出すタイマーを使用する計画がありました。Work_Completed
しかし、同僚の何人かは、バックグラウンド ワーカーを使用し、イベント時にワーカーを再実行するように言いました。これら2つの違いは何ですか?タイマーもバックグラウンド スレッドを作成しますか? 長時間実行されるタスクに最適なのはどれですか?
4 に答える
Timer
リソース消費に関しては、ほぼ確実にA の方が適しています。ABackgroundWorker
は、そのタスクのためだけに新しいスレッドを作成しようとしています。新しいスレッドの作成は、かなりコストのかかる操作です。多くの異なるタイマーの実装があり、それらの実装はさまざまですが、それらは通常、定期的にイベントを発生させる OS ツールに依存することになります。これは、新しい専用スレッドを開始するよりも望ましいことです。
オブジェクトの主な違いのほとんどは、Timer
「準備ができた」ときに何をするかです。新しいスレッド プール スレッドを作成するものもあります。ハンドラーを実行するためにタイマーのすべてのインスタンスによって共有される専用スレッドを持っているものもあれば、コードを UI スレッド (または他の同期コンテキスト) にマーシャリングするものもあり、おそらく後者が必要です。使用している特定の UI フレームワークで使用できるようになっているタイマーを使用すると、それが表示される動作になります。
BackgroundWorker は ThreadPool にスレッドを作成します (非同期デリゲート呼び出しを介して)。BCL タイマーは、ThreadPool スレッドを使用してイベントを発生させるか、場合によっては UI スレッドで tick/elapsed/etc イベントを発生させます (WinForms タイマーまたは ISynchronizeInvoke が提供されている Timers.Timer の場合)。 )。
BackgroundWorker は、UI 環境のバックグラウンド スレッドに最適な API を提供します。メソッドをバックグラウンド スレッドで (DoWork イベントを介して) 実行できるようにし、スレッド間の呼び出しを気にすることなく、UI スレッド (ProgressChanged および RunWorkerCOMpleted イベント) で進行状況と完了を通知する簡単な方法を提供します。
WinForms タイマーは UI スレッドで実行され、その経過イベントから任意の UI 要素に触れても安全です。ただし、正確な間隔で実行されるとは限りません。UI スレッドで何が起こっているかに依存します。重要なことを 1 つ繰り返します。このオプションにはバックグラウンド スレッドはありません。
Threading.Timer は一種の「醜い API」タイマーです。Timers.Timer は単に Threading.Timer をより適切な API にラップし、UI スレッドで (SynchronizingObject プロパティを介して) 経過したイベントを自動的に呼び出す方法を提供します。SynchronizingObject プロパティを設定すると、コードはバックグラウンド スレッドで実行されず、すぐに UI スレッドにマーシャリングされます。
一般に、UI 内では、BackgroundWorker は他の選択肢よりも簡単に処理できます。
A standard System.Windows.Forms.Timer
should be fine. It calls its callback on the UI thread which means that while you are processing inside the callback it will potentially freeze your UI responsiveness. But that's only an issue if you do a lot of work inside the callback or if you block the thread.
To avoid blocking the thread, just execute an asynchronous WCF call.
A BackgroundWorker
makes no sense for what you want to do. All you want to do is to wait 500ms before executing some code so just use a System.Windows.Forms.Timer
.