吊り下げに問題がありました(hereを参照)。研究中にSetResult
をTaskCompletionSource
に呼び出すと、実際にSetResult
というスレッドのコンテキストで待機中の継続が呼び出されていることがわかりました(これはthis answerという質問に多少関連しています)。私の場合、これはawait(ASP.NETリクエストスレッド)を開始したスレッドとは別のスレッド(スレッドプールワーカースレッド)です。タスクを完了したときにSynchronizationContextを手動でキャプチャして適用する
これがなぜハングアップするのかまだわかりませんが、私はSetResult
を元のコンテキストに強制しようとしました。リクエストスレッドにawaitを入力する前にSynchronizationContext.Current
の値を保存し、SynchronizationContext.SetSynchronizationContext
を介して手動でワーカースレッドに適用したところ、SetResult
を呼び出す直前です。これによりハングが解消され、ConfigureAwait(false)
を指定せずにすべての非同期メソッドを待つことができます。
私の質問は、SynchronizationContext
を手動でキャプチャして適用するのに合理的かつ正しいアプローチですか? FWIW、私はSetResult
デリゲートで簡単にPost()
を実行しようとしましたが、それでもハングしました。私は明らかにここの私の快適ゾーンから少し外れています...何が起こっているのか理解してください!
SetResult(またはその欠如)の保証について...少し拡大できますか?*観察された効果は、手動で適用されたコンテキストがワーカースレッドあなたが暗示しているように、私は荒々しい詳細についてもっと知りたいと思っています! – aoven
TPLにはいくつかのポイントがありますスレッドのローカルステートを変更し、このコールチェーンを持っている場合:A => SetResult => Bならば、Bはそのステートを参照します。もしチェーンがA => SetResult => QueueToThreadPool(B)ならば、Bはクリーンな状態を見るでしょう。これはあなたが見ていることを説明していますか?= – usr
私は確実にどちらかの方法を言うことができません...私のチェーンは実際にはA => QueueToThreadPool => SetResult => Bであり、コールが成功しワーカースレッドがブロックされないため、SetResultが継続を直接呼び出さないと判断しました。ブロックされている唯一のもの(私には目に見える)は待っています。RunContinuationsをTaskCompletionSourceと同時に渡すと、Post/Sendを呼び出すのと同じように効果がないようです。 あなたは以前に問題が継続していると言いました...実行されることがないと(ブロックは待っている回線で発生します)、どんな種類の問題が起こる可能性がありますか? – aoven