私はasync数年間生産で使用してきました。私が推奨するコアとなる「ベスト プラクティス」がいくつかあります。
asyncコードでブロックしないでください。async「ずっと」を使います。(結果:を使用する必要がない限り、を使用することasync Taskをお勧めします)。async voidasync void
ConfigureAwait(false)「ライブラリ」メソッドで可能な限り使用してください。
あなたはすでに「asyncずっと下まで」の部分を理解しており、ConfigureAwait(false)役に立つポイントに来ています。
別のasyncメソッドAを呼び出すasyncメソッドがあるとしますB。Aの結果で UI を更新しますが、UI にBはB依存しません。したがって、次のようになります。
async Task A()
{
var result = await B();
myUIElement.Text = result;
}
async Task<string> B()
{
var rawString = await SomeOtherStuff();
var result = DoProcessingOnRawString(rawString);
return result;
}
この例でBは、UI コンテキストで実際に実行する必要がないため、「ライブラリ」メソッドを呼び出します。現在、UI スレッドで実行されているためB 、DoProcessingOnRawString応答性の問題が発生しています。
したがって、ConfigureAwait(false)すべての in に a をawait追加しBます。
async Task<string> B()
{
var rawString = await SomeOtherStuff().ConfigureAwait(false);
var result = DoProcessingOnRawString(rawString);
return result;
}
これで、 がingB後に再開すると(実際に する必要があると仮定して)、UI コンテキストではなくスレッド プール スレッドで再開されます。完了すると、スレッド プールで実行されていても、UI コンテキストで再開されます。awaitSomeOtherStuffawaitBA
UI コンテキストに依存ConfigureAwait(false)するAため、追加できません。A
また、タスクを明示的にスレッド プールにキューイングするオプションもあり ( await Task.Run(..))、特定の CPU 集中型機能がある場合は、これを行う必要があります。しかし、パフォーマンスが「何千ものペーパー カット」に苦しんでいる場合は、 を使用して、多くの「ハウスキーピング」をスレッド プールConfigureAwait(false)にオフロードできます。async
私のイントロ ポストが役に立つかもしれません(「理由」の詳細が説明されています)。また、asyncFAQにも多くの優れたリファレンスがあります。