.NET 3.5およびWPFのディスパッチャーの概念は、.NET 2.0のバックグラウンドスレッドとどのように異なりますか?
たとえば、以下のステートメントの違いは何ですか。
delegate.Invoke/BeginInvoke
と
this.dispatcher.Invoke/BeginInvoke
.NET 3.5およびWPFのディスパッチャーの概念は、.NET 2.0のバックグラウンドスレッドとどのように異なりますか?
たとえば、以下のステートメントの違いは何ですか。
delegate.Invoke/BeginInvoke
と
this.dispatcher.Invoke/BeginInvoke
ディスパッチャは、イベントが送信されるキューと考えることができます。ディスパッチャはUIスレッドで実行され、UIのイベントを実行します。ウィンドウでは、UIコントロールはそれらを作成したスレッドによってのみ変更できるため、UIへの変更はUIスレッドから行う必要があります。これが、ウィンドウ要素を変更する操作をUIに送信する必要がある重要な理由の1つです。発車係。
同様に、バックグラウンドスレッドはUIとは異なるスレッドです。したがって、これらのスレッドの1つで実行されるものは、UIに影響を与えたりブロックしたりすることはありません。
BeginInvokeとInvokeの概念は、次のように考えることができます。
これがディスパッチャとバックグラウンドスレッドにどのように関係するかは、まったく別の問題です。Justinが言うように、Dispatcherは、UIスレッドがアイドル状態になるたびに実行する処理のキューを処理します。ディスパッチャでBeginInvokeを呼び出すバックグラウンドスレッドは、ディスパッチャが処理に取り掛かっていなくても、すぐに戻ります。代わりにInvokeが使用された場合、バックグラウンドスレッドはUIスレッドが処理を完了するまでブロックします。Silverlightでは、ディスパッチャーにInvokeがないことに注意してください。ほとんどの場合、UIスレッドが作業を処理している間、バックグラウンドスレッドをブロックしたくないでしょう。
逆に、Delegate.BeginInvokeは、スレッドプール内のワーカースレッドを使用します。UIスレッド(または実際には任意のスレッド)を使用している場合は、デリゲートでBeginInvokeおよびInvokeを呼び出すことができます。BeginInvokeは、ワーカースレッドを使用して、上記と同じセマンティクスを使用してデリゲートを呼び出します。ただし、Invokeは別のスレッドを使用しません。呼び出し元のスレッドのコンテキストでデリゲートを同期的に呼び出し、完了すると戻ります。
スレッド間で同期実行を使用する場合は注意が必要ですが、あまり注意しないとデッドロックが発生することがよくあります。
ディスパッチャを使用して長時間実行される操作を実行すると、現在の操作とは異なる優先度で、UIスレッドで実行されます。ここでの問題は、通常、長時間実行する操作に可能な限り多くの帯域幅を持たせたいということです。ディスパッチャーの下で実行すると、UIによって抑制されます。
ディスパッチャのポイントは、バックグラウンドスレッドへのアンカーをUIに戻すことです。これにより、たとえば、操作の進行状況についてUIに更新を提供できます。
バックグラウンドで操作を実行し、実行をUIに延期する場合は、backgroundworkerまたは新しいタスクライブラリを使用します。ディスパッチャを使用して、更新をUIにマーシャリングします。
両方のメソッドによって呼び出された操作は、UIスレッドで実行されるイベントキューに配置されます。Invokeは同期的に発生し、操作が完了するまでブロックされます。BeginInvokeは非同期的に発生し、呼び出し元のメソッドが実行を継続できるようにします。