SynchronizationContext は何をしますか? 質問する

SynchronizationContext は何をしますか? 質問する

『プログラミング C#』という本には、次のようなサンプル コードがいくつか掲載されていますSynchronizationContext

SynchronizationContext originalContext = SynchronizationContext.Current;
ThreadPool.QueueUserWorkItem(delegate {
    string text = File.ReadAllText(@"c:\temp\log.txt");
    originalContext.Post(delegate {
        myTextBox.Text = text;
    }, null);
});

私はスレッドの初心者なので、詳しく答えてください。まず、コンテキストが何を意味するのか、プログラムは に何を保存するのかがわかりません。originalContextまた、メソッドが起動されるとPost、UI スレッドはどの
ような処理を行いますか? 馬鹿げた質問をしていたら、訂正してください。よろしくお願いします!

編集: たとえば、myTextBox.Text = text;メソッドにだけ記述した場合、違いは何でしょうか?

ベストアンサー1

SynchronizationContext は何をしますか?

簡単に言えば、SynchronizationContextコードが実行される可能性のある場所を表します。SendまたはPost方法その場所で が呼び出されます。 (Postは の非ブロッキング/非同期バージョンですSend。)

すべてのスレッドは、SynchronizationContextそれに関連付けられたインスタンスを持つことができます。実行中のスレッドは、静的SynchronizationContext.SetSynchronizationContextメソッド実行中のスレッドの現在のコンテキストは、SynchronizationContext.Current財産

先ほど書いたように(各スレッドには同期コンテキストが関連付けられている)、aはSynchronizationContext必ずしもaを表すわけではない。特定のスレッド; また、渡されたデリゲートの呼び出しを転送することもできますいくつかのうちのいずれかスレッド(例えば、ThreadPoolワーカースレッド、または(少なくとも理論上は)特定のCPUコア、あるいは別のネットワークホストデリゲートが実行される場所は、使用されるタイプによって異なりますSynchronizationContext

Windows フォームは、最初のフォームが作成されたスレッドに をインストールしますWindowsFormsSynchronizationContext。(このスレッドは一般に「UI スレッド」と呼ばれます。) このタイプの同期コンテキストは、渡されたデリゲートをまさにそのスレッドで呼び出します。Windows フォームは、他の多くの UI フレームワークと同様に、コントロールの操作をそれらが作成されたのと同じスレッドでのみ許可するため、これは非常に便利です。

myTextBox.Text = text;メソッド内に記述するだけで違いは何でしょうか?

渡したコードはThreadPool.QueueUserWorkItemスレッド プールのワーカー スレッドで実行されます。つまり、myTextBox作成されたスレッドでは実行されないため、Windows フォームは遅かれ早かれ (特にリリース ビルドの場合)、myTextBox別のスレッドからアクセスできないことを通知する例外をスローします。

myTextBoxこのため、その特定の割り当ての前に、何らかの方法でワーカー スレッドから「UI スレッド」(作成された場所) に「切り替える」必要があります。これは次のように行われます。

  1. UI スレッドにいる間に、Windows フォームをキャプチャし、後で使用するためにSynchronizationContextその参照を変数 ( ) に格納します。この時点でクエリを実行する必要があります。 に渡されたコード内でクエリを実行すると、スレッド プールのワーカー スレッドに関連付けられている同期コンテキストが取得される可能性があります。Windows フォームのコンテキストへの参照を格納すると、いつでもどこでもそれを使用して、UI スレッドにコードを「送信」できます。originalContextSynchronizationContext.CurrentThreadPool.QueueUserWorkItem

  2. UI 要素を操作する必要があるときはいつでも (ただし、UI スレッド上にない場合、または UI スレッド上にない可能性がある場合)、 を介して Windows フォームの同期コンテキストにアクセスしoriginalContext、UI を操作するコードを または に渡しSendますPost


最後にコメントとヒント:

  • 同期コンテキストとはしませんが代わりに行うことは、特定の場所/コンテキストで実行する必要があるコードと、 に渡さずに通常どおり実行できるコードを通知することですSynchronizationContext。これを決定するには、プログラミング対象のフレームワーク (この場合は Windows フォーム) のルールと要件を知っておく必要があります。

    Windowsフォームのこの簡単なルールを覚えておいてください。コントロールやフォームには、それを作成したスレッド以外からアクセスしないでください。どうしてもアクセスする必要がある場合は、SynchronizationContext上記のメカニズムを使用するか、Control.BeginInvoke(これは、まったく同じことを実行する Windows フォーム固有の方法です)。

  • .NET 4.5以降でプログラミングしている場合は、、、などを明示的に使用するコードを新しいものに変換することで、作業がはるかに簡単になりますSynchronizationContextThreadPool.QueueUserWorkItemcontrol.BeginInvokeasync/awaitキーワードそしてそのタスク並列ライブラリ (TPL)、つまり、TaskそしてTask<TResult>クラス。これらは、UI スレッドの同期コンテキストをキャプチャし、非同期操作を開始し、その後 UI スレッドに戻って操作の結果を処理できるようにするという作業を非常に高いレベルで処理します。

おすすめ記事