2017-03-22 2 views
7

私は、デスクトップのwinformアプリケーションの非常に大きく古いコードベースに取り組んでいます。このコードベースでは、主にBackgroundWorkerを使用してバックグラウンドスレッドで実行される多くの操作があります。非同期/待機コードでのAsyncLocal <T>の影響を教えてください。

このコードベースの共通パターンは、実行中のスレッドにアーティファクトをバインドすることによって複雑さを隠すことです。たとえば、データベース接続とトランザクションは[ThreadStatic]フィールドに格納されます。

これを変更して、async/awaitコードを使い始めると、プールの任意のスレッドでタスクを実行し、他のスレッドでタスクを実行できるようになります。ConfigureAwait(false)を使用してください。 [ThreadStatic]async/awaitでうまく再生されないことを知っています。代わりにAsyncLocal<T>を使用するように提案しています。

大きなコードベースに取り組んでいることを考えると、前に述べたように、私はasync/awaitに一度に切り替えることができず、徐々にこの変更を行う必要があります。したがって、以前のコード[ThreadStatic]AsyncLocal<T>に変更されますが、コードの大部分はBackgroundWorkerを使用し続け、1つのasync/await行のコードをヒットしません。

質問
これは機能しますか?新しいasync/awaitコードで動作するコンテキストフローを定義できるようにする必要があります。また、すべてのスレッドの内容を互いに独立させておくことに依存していた古い非同期コードを使用し続けます。[ThreadStatic]

私が間違っていて間違った経路を辿った場合、提案は非常に歓迎されます。

答えて

7

うまくいくはずです。

AsyncLocal<T>は、論理呼び出しコンテキストを抽象化したものです。私はthe logical call context and how it interacts with async/awaitを古いブログ記事で詳しく説明しています。

要約すれば、おそらくうまくいくが、AsyncLocal<T>の1つの側面はThreadStaticとはかなり異なる。

AsyncLocal<T>の値に書き込むと、その値が現在の論理呼び出しコンテキストに設定されます。 asyncメソッドは論理呼び出しコンテキストのコピーオンスコープを確立するので、内にと書き込むと、asyncメソッドでは、新しいという新しい値を含む論理呼び出しコンテキストが作成されます。これにより、asyncメソッドはネストされた方法でそれを使用することができます。ここで、「内部」コンテキストは「外部」コンテキストを上書きできます。 ただし、「内部」コンテキスト値は、呼び出し元に返されることはありません。 「外部」コンテキストが再開されると、「内部」コンテキストが完全に置き換えられます。

方法のいずれもがasyncされず、値は唯一、自分のスレッドから設定されている場合は、そのスレッドがちょうど単一の論理コールコンテキストを持っており、値がThreadStaticとしてちょうど同じように動作します読み/書き込み。