2017-01-20 15 views
1

メソッドDispatcherのオブジェクトで出会った。メソッドの簡略化されたバージョンです。PushFrameは何のために必要ですか?

public void PushFrame(DispatcherFrame frame) 
{ 
    // Stuff 
    _frameDepth++; 

    while(frame.Continue) 
    { 
     // Getting and dispatching messages 
    } 

    _frameDepth--; 
    // Stuff 
} 

つまり、新しいメッセージ処理ループが開きます。しかし、私は本当にそのような利点を理解することはできません。 PushFrameはどのような目的のために使用されていますか?その使用法の良い例はありますか?私にとっては、この方法は明らかな誤りにつながりそうにないようです。

+1

https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.pushframe.aspx – crowchirp

+0

私はドキュメントを読んでいます。私はそれがどのように機能するのか知っていますが、私はこの方法の目的を理解できません。なぜPushFrameメソッドが必要です – LmTinyToon

答えて

6

これは、WPFプログラムのディスパッチャループにとって不可欠な配管です。 Windows上のすべてのGUIプログラムには1つがあり、それはproducer-consumer problemへの普遍的な解決策です。 OSやその他のプログラムが生成され、WPFプログラムのUIスレッドが消費される場所。 GUIアプリケーションを厳しく要求すると、GUIを実装するライブラリコードは決してスレッドセーフではありません。ここでループを簡単に見ることができます。スレッドセーフなキューがループによって空になっているのを見ることはできません。それはOSに組み込まれています。

ループは、Application.Run()の呼び出しによって開始されます。 WPFアプリケーションでは分かりにくく、App.xamlファイルのほとんどのアプリケーションで自動生成されます。最初の "フレーム"がプッシュされると、ループ内にある限り、アプリは実行を続けます。イベントハンドラにブレークポイントを設定すると、コールスタックデバッガウィンドウに常に表示されます。あなたのアプリのMainWindowを閉じることは、ループが終了する通常の方法です。これによりRun()メソッドが返され、プロセスを終了するUIスレッドが終了します。

ネストされたディスパッチャループが必要なシナリオがいくつかあります。 「モーダルループ」。毎日使用するモーダルループの例は、マウスをクリックしてウィンドウの角にドラッグすることです。すべてのマウスとキーボードの入力がウィンドウのサイズや位置を変更するようになりましたが、通常の方法でUIを操作するために使用されなくなりました。マウスを離すと、そのループが終了します。このディスパッチャループはOSに組み込まれており、WPFでは実行されません。

しかし、WPFはこのようなモーダルループにも使用されています。標準的な例はWindow.ShowDialog()メソッドです。このメソッドは、ダイアログが閉じられるまで戻りません。 WPFが内部的にPushFrame()を再度呼び出すことで達成されます。デバッガで試してみると、両方のPushFrame呼び出しが[コールスタック]ウィンドウに表示されます。最初のものはShowDialog()が呼び出したもので、2番目はアプリケーションであるものです。Run()が呼び出されました。ダイアログにダイアログが表示されると、さらに多くの情報が得られます。

あまり明白でない例は、UIスレッドでDispatcher.Invoke()を呼び出すことです。呼び出されたメソッドが返るまで返されないメソッド。通常は少しバグですが、それを拒否する理由はありませんでした。警告の言葉は適切かもしれませんが、モーダルループはかなり危険です。彼らには、の再入荷バグが発生した。 DoEvents()メソッドが非常に悪名高いバグです。 ShowDialog()がUI内の他のすべてのウィンドウを無効にする大きな理由です。

+0

大きな説明。ありがとう – LmTinyToon

1

PushFrameはどのような目的のために使用されていますか?

現在のディスパッチャにフレームをプッシュするために内部的に使用されます。ディスパッチャキューがどのように詳細に機能するかは、非常に大きな話題ですが、次の回答が参考になるはずです。

Understanding the Dispatcher Queue

その使用の良い例はありますか?

たとえば、何らかの理由で非同期メソッドを同期して呼び出し、タスクが完了するまでメッセージを引き続き送りたい場合。あなたはGitHubの上ステファン・クリアリーさんAsyncCTPUtilライブラリでこれの具体的な実装例を見つける:https://github.com/StephenCleary/AsyncCTPUtil/blob/master/AsyncTestUtilities/WpfContext.cs

詳細については、こちらを彼の答えを参照してください:

How would I run an async Task<T> method synchronously?

また、次のリンクを参照してくださいことができます: https://social.msdn.microsoft.com/Forums/vstudio/en-US/650e69f9-5f4d-4d77-8107-93fb6646f26d/solved-block-synchronous-method-while-waiting-for-async-method-to-complete?forum=wpf

関連する問題