私はデスクトップwinformアプリケーションの非常に大きくて古いコードベースに取り組んでいます。このコードベースでは、主にBackgroundWorker
を使用して、バックグラウンドスレッドで実行される多くの操作があります。
このコードベースの一般的なパターンは、実行中のスレッドにアーティファクトをバインドすることで複雑さを隠すことです。たとえば、データベース接続とトランザクションは[ThreadStatic]
フィールドに保存されます。
これを変更して、async/await
コードの使用を開始し、プールの任意のスレッドでタスクを実行し、ConfigureAwait(false)
を使用してタスクを他のスレッドで実行し続けることができるようにします。 。 [ThreadStatic]
がasync/await
とうまく機能しないことは知っています。代わりに、AsyncLocal<T>
を使用することを提案するいくつかの回答をここで読みました。
前述のように、大規模なコードベースで作業しているため、1回のショットでどこでもasync/await
に切り替えることができず、この変更を徐々に行う必要があります。したがって、以前は[ThreadStatic]
があったコードはAsyncLocal<T>
に変更されますが、コードの大部分は引き続きBackgroundWorker
を使用し、コードの1行のasync/await
にヒットしません。 。
質問
これは機能しますか?新しいasync/await
コードで機能するある種のコンテキストフローを定義できる必要があります。また、[ThreadStatic]
に依存していた古い非同期コードでも機能し続け、すべてのスレッドをそれぞれから独立させます。その他。
私が完全に間違っていて、間違った道を進んでいる場合、提案は大歓迎です。
動作するはずです。
AsyncLocal<T>
は、論理呼び出しコンテキストを抽象化したものです。 論理呼び出しコンテキストとそれがasync
/await
とどのように相互作用するか については、古いブログ投稿で詳しく説明しています。
要約すると、おそらく正常に機能しますが、ThreadStatic
とはまったく異なるAsyncLocal<T>
の1つの側面があります。
AsyncLocal<T>
値に書き込むと、その値が現在の論理呼び出しコンテキストに設定されます。 async
メソッドは、論理呼び出しコンテキストのコピーオンライトスコープを確立するため、内内に書き込むとasync
メソッド、新しい値を含むnew論理呼び出しコンテキストを作成します。これにより、async
メソッドでネストされた方法で使用できるようになり、「内部」コンテキストが「外部」コンテキストを上書きできます。 ただし、「内部」コンテキスト値が呼び出し元に逆流することはありません。 「外部」コンテキストが再開されると、「内部」コンテキストが完全に置き換えられます。
どのメソッドもasync
でなく、値が独自のスレッドからのみ設定されている場合、そのスレッドには単一の論理呼び出しコンテキストがあり、値の書き込み/読み取りはThreadStatic
。