ディスパッチャーキューを理解するのに助けが必要だと思います。
新しい作業が到着すると、ディスパッチャキューの先頭に追加され、ディスパッチャが作業項目を処理する場合は、最初から削除されます。
より一般的に言えば、作業がある場合は、キュー内にFIFOの方法で格納され、作業が残っていない限り処理されます。
MSDNドキュメント ここ はloop
とframe
を参照しています。
_The Dispatcher processes the work item queue in a loop. The loop is referred to as a frame.
_
しかし、このコンテキストでのループはどこにありますか?私にとって、ループとは何かを繰り返すものであり、最後に達すると最初からやり直します。
そして、frame
の概念は何ですか? MSDNのドキュメントによると、フレームはキュー内の作業項目のパンチですか?それが本当なら、静的メソッドDisptatcher.PushFrame()
はどのように使用されるべきですか?
そして、最も興味深い質問は、キューの現在の状態、特にキューにあるアイテムの数を取得する方法があるかどうかです。
以前に呼び出された(したがってDispatcherキューに入れられた)メソッドが実行された場合、そのメソッドはすぐにキューから削除されますか、それとも別の期間内部に残りますか?
私は知っています、とても多くの質問:-)
Dispatcher
を取り巻くドキュメントはほとんどないので、内部の仕組みについて知るために少し分解する必要があります。
ディスパッチャは基本的に、アプリケーションの Message Pump を回避する作業を実行するものです。問題の1つは、 windowsメッセージループ の上にあります。
結果として、アプリケーションDispatcherは1つだけになります。つまり、Application.Current.Dispatcher
からアクセスできるグローバルディスパッチャオブジェクトです。ドキュメントによると、Dispatcher.CurrentDispatcher
にアクセスすることで、他のディスパッチャが可能です。
現在実行中のスレッドのディスパッチャーを取得し、スレッドにまだ関連付けられていない場合は新しいディスパッチャーを作成します。
ただし、この新しいディスパッチャでRun
を呼び出すとブロックされます。
Dispatcher.PushFrame
を実行すると、内部実行ループがディスパッチャーにプッシュされます。これが frame の一般的な考え方です。 DispatcherObject
などのDispatcherFrame
から継承するものはすべて、ディスパッチャが現在のものに設定されます。これは、コンストラクターを調べることで確認できます。
private Dispatcher _dispatcher;
protected DispatcherObject()
{
this._dispatcher = Dispatcher.CurrentDispatcher;
}
もちろん、単純なイベントループを持つだけでは十分ではありません。他の作業を強制的に実行するために、現在のイベントループを破壊する必要がある場合があります。そして、それがあなたがDispatcherFrame
を持っている理由です。これが実際にイベントループを構成するものです。フレームをディスパッチャにプッシュすると、次のようになります。
while (frame.Continue)
{
if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0))
{
break;
}
this.TranslateAndDispatchMessage(ref msg);
}
メッセージが取り出された後、ディスパッチャの優先キューが評価されるのはTranslateAndDispatchMessage
です。
ディスパッチャでの操作の実行に時間がかかると、イベントループが一時的に停止し、シグナリングに応答しないため、アプリケーションが応答を停止したように見えます。
これが記事です フレームを使用して、イベントループをすぐに実行できるようにすることで、UIを強制的に応答させます。
キューへのアクセスは、そのままではディスパッチャ外のキューの状態を知ることはできません。これは内部の詳細であり、公開されていないことは合理的です。