問題タブ [synchronizationcontext]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - C#非同期/待機コードで「コンテキスト」とは正確には何を意味しますか?
withobj
の前後にオブジェクト参照 ( ) がある単純な C# async/await コードを見てみましょう。await
ConfigureAwait(false)
ConfigureAwait(false)
キャプチャされた元のコンテキストに継続をマーシャリングしない ことを意味するようです-わかりましたが、それは実際にはどういう意味ですか? 上記のコードを試してみたところ、正しく参照されました (別のスレッドで再開した場合でも)。obj
そのため、「コンテキスト」はスレッドの作業メモリ (つまり、スレッド ローカル ストレージ) ではないようです。では、「文脈」には何が含まれているのでしょうか。したがって、それは本当に何を意味するのでしょうか
継続をマーシャリングして、キャプチャした元のコンテキストに戻します
c# - 非同期コールバックを呼び出すライブラリで ConfigureAwait(false) を使用する必要がありますか?
ConfigureAwait(false)
C# で await/async を使用する場合、 をいつ使用するかについては、多くのガイドラインがあります。
ConfigureAwait(false)
同期コンテキストに依存することはめったにないため、ライブラリコードで使用することが一般的に推奨されているようです。
ただし、関数を入力として受け取る非常に一般的なユーティリティ コードを作成しているとします。簡単な例としては、単純なタスクベースの操作を簡単にするための次の (不完全な) 関数コンビネータがあります。
地図:
フラットマップ:
問題は、ConfigureAwait(false)
この場合に使用する必要があるかどうかです。コンテキストキャプチャがどのように機能するかわかりません。閉鎖。
一方では、コンビネータが機能的な方法で使用される場合、同期コンテキストは必要ありません。一方、人々は API を誤用し、提供された関数でコンテキスト依存のことを行う可能性があります。
1 つのオプションは、各シナリオ (Map
およびMapWithContextCapture
または何か) ごとに個別のメソッドを用意することですが、見苦しく感じます。
別のオプションは、マップ/フラットマップからおよびへのオプションを追加することかもしれませんConfiguredTaskAwaitable<T>
が、awaitables はインターフェイスを実装する必要がないため、多くの冗長なコードが発生し、私の意見ではさらに悪化します。
実装されたライブラリが提供されたマッピング関数でコンテキストが必要かどうかについて仮定をする必要がないように、責任を呼び出し元に切り替える良い方法はありますか?
それとも、さまざまな仮定がないと、非同期メソッドがうまく構成されないというのは単なる事実ですか?
編集
いくつかのことを明確にするために:
- 問題は存在します。ユーティリティ関数内で「コールバック」を実行すると、 を追加
ConfigureAwait(false)
すると null 同期が発生します。環境。 - 主な問題は、この状況にどのように取り組むべきかということです。誰かが同期を使用する可能性があるという事実を無視する必要があります. または、オーバーロードやフラグなどを追加する以外に、責任を呼び出し元に移す良い方法はありますか?
いくつかの回答が言及しているように、メソッドにbool-flagを追加することは可能ですが、私が見るように、APIを介して伝播する必要があるため、これもあまりきれいではありません(上記のものに応じて、より多くの「ユーティリティ」機能)。
c# - 同期コンテキストを介したカスタム メッセージ ボックス - 破棄されたオブジェクトにアクセスできない
私はここでかなり奇妙な状況にいます。(組み込みの代わりに) カスタム MessageBox フォームを作成しましたMessageBox.Show
。以下のコードは、必要なときにフォームを呼び出すために使用するものです。
これを実行するmessageBox.ShowDialog();
と、messageBox インスタンスが既に破棄されているというエラー メッセージが表示されます。
コードを同期コンテキストに投稿したとき、MainForm が (他のスレッドとは対照的に) コード自体を実行すると確信していましたが、messageBox が既に破棄されていると表示される理由がわかりません。
何か案は?
c# - Synchronization.Context は Post では null ですが、Send ではありません
Prism のイベント アグリゲーターを使用するアプリケーションで、一部の動作を単体テストしようとしています。単体テストしようとしているコードの 1 つは、UI スレッドでイベントをサブスクライブすることです。EventAggregator の実装を掘り下げてみると、SynchronizationContext.Post
.
この答えは良い回避策かもしれないと思いましたが、より単純な修正を使用することになりました.ユニットテストの開始時に同期コンテキストを明示的に設定します-これは、読み込もうとするまで機能しますSynchronizationContext.Current
私が完全に理解していない行動に私を導きました:
Post が非同期で発生し、Send が同期で発生することを理解しています。スレッド デバッグ ウィンドウでそれを見ると、非同期呼び出しが行うと予想されるように、実際には別のスレッド ID にキックオーバーします。
私が理解しようとしているのは、同期コンテキストに関数を実行するように指示するとき、同期または非同期に関係なく、そのコンテキストが保持されることを期待していると思います。同期呼び出しでは保持されますが、非同期では保持されません。
この動作が見られるのはなぜですか? また、単体テストでそれをどのように補正できますか?
c# - ワーカー スレッドから Microsoft.Owin 自己ホスト型 Web API と通信する方法
別のスレッドから Microsoft.Owin.Hosting.WebApp インスタンスと通信する方法についてのガイダンスを探しています。
まず、Web サーバーとワーカー スレッドを開始します。すなわち。
ここで、ワーカー スレッドがイベントを検出したときにコードを実行したいと考えています。このコードは、Web サーバーおよび同じ SynchronizationContext と同じスレッドで実行する必要があります (Web アプリは完全にシングル スレッドで非同期です)。これらのイベントを Web API リクエストと同じ非同期の方法で処理し、それらの間でデータを共有できるようにしたいと考えています。
問題は、上記の「アプリ」が単に IDisposable であることです。WebAPI リクエストの SynchronizationContext にアクセスする方法がありません。Web アプリを別の方法でインスタンス化する方法はありますか?
c# - SynchronizationContext - 奇妙な動作
このコードは正常に動作します。でソースを取得しMessageBox
ます。しかし、使用するとデッドロックが発生するのはなぜvar task = GetSource3()
ですか? ConfigureAwait(false)
コンテキスト切り替えを使用して回避しているので、うまくいくはずだと思いました