私はasync
数年間生産で使用してきました。私が推奨するコアとなる「ベスト プラクティス」がいくつかあります。
async
コードでブロックしないでください。async
「ずっと」を使います。(結果:を使用する必要がない限り、を使用することasync Task
をお勧めします)。async void
async 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 コンテキストで再開されます。await
SomeOtherStuff
await
B
A
UI コンテキストに依存ConfigureAwait(false)
するA
ため、追加できません。A
また、タスクを明示的にスレッド プールにキューイングするオプションもあり ( await Task.Run(..)
)、特定の CPU 集中型機能がある場合は、これを行う必要があります。しかし、パフォーマンスが「何千ものペーパー カット」に苦しんでいる場合は、 を使用して、多くの「ハウスキーピング」をスレッド プールConfigureAwait(false)
にオフロードできます。async
私のイントロ ポストが役に立つかもしれません(「理由」の詳細が説明されています)。また、async
FAQにも多くの優れたリファレンスがあります。