私のasync
/await
イントロ、特に「コンテキスト」について説明している部分が役立つかもしれません。
一般的な例は、いくつかの情報をダウンロードし、それをデータ構造に解析してから、次のようにUIを更新することです。
private async Task GetInfoAndUpdateUIAsync()
{
var info = await GetInfoAsync();
UpdateUI(info);
}
private async Task<MyInfo> GetInfoAsync()
{
using (var client = new HttpClient())
{
var httpResponse = await client.GetStringAsync(...);
return MyInfo.Parse(httpResponse);
}
}
ウォークスルー
GetInfoAndUpdateUIAsync
UIコンテキスト(async void
イベントハンドラーなど)から呼び出すことができます。
実行をGetInfoAndUpdateUIAsync
開始すると、UIスレッドで(同期して)実行されます。最初に行うことは、を呼び出すことGetInfoAsync
です。
GetInfoAsync
また、UIスレッドで(同期的に)実行を開始します。を作成しHttpClient
、それを使用してURLからのデータのダウンロードを開始します。をGetInfoAsync
実行するawait
と、状態が保存され、不完全ながに返さTask<MyInfo>
れGetInfoAndUpdateUIAsync
ます。
GetInfoAndUpdateUIAsync
返さawait
れたに対してを実行しますがTask<MyInfo>
、これは完全ではありません。したがって、状態も保存して戻ります。async void
これは、元の呼び出し元(たとえば、イベントハンドラー)にバックアップし続けます。UIスレッドは、他の作業を自由に行えるようになりました。
データのHttpClient
ダウンロードが完了すると、返さTask<string>
れるデータは完了します。GetInfoAsync
これにより、UIスレッドでの継続がスケジュールされます。
GetInfoAsync
その後、UIスレッドで実行を継続します。UIスレッドで実行している間、応答をデータ構造()に解析し、メソッドの最後に到達して、以前に返されMyInfo.Parse
たタスクを完了します。Task<MyInfo>
完了すると、UIスレッドへTask<MyInfo>
の継続をスケジュールします。次に、UIスレッドで(同期的に)呼び出します。GetInfoAndUpdateUIAsync
GetInfoAndUpdateUIAsync
UpdateUI(info)
結論
これは、async
メソッドのさまざまな部分がUIスレッドで(同期的に)実行されるが、UIスレッドがブロックされていない例です。
async
メソッドがその後も続く場合await
、Task
デフォルトでは同じコンテキストで再開されます。この「コンテキスト」は、SynchronizationContext
nullでない場合は現在(UIコンテキストなど)であり、そうでない場合は現在TaskScheduler
です。の結果を待つことでデフォルトの動作をオーバーライドできますConfigureAwait(false)
。これにより、メソッドの継続がスレッドプールスレッドで実行されます。
もう1つのメモ
この例では、UIスレッドで実際に実行する必要のないいくつかのことをUIスレッドで実行しています。特に、HTTP応答のMyInfo
構造への解析。
GetInfoAsync
デフォルトのコンテキストキャプチャをオーバーライドすることで、もう少し効率的に変更できます。
private async Task<MyInfo> GetInfoAsync()
{
using (var client = new HttpClient())
{
var httpResponse = await client.GetStringAsync(...).ConfigureAwait(false);
return MyInfo.Parse(httpResponse);
}
}
これで、HTTP応答が着信してGetInfoAsync
実行を継続すると、UIスレッドではなくスレッドプールスレッドで実行を継続します。したがってMyInfo.Parse
、UIではなくスレッドプールで実行されます。解析Task<MyInfo>
が完了すると、が完了GetInfoAndUpdateUIAsync
し、UIスレッドで実行を継続します。
UIスレッドで実行する必要がGetInfoAndUpdateUIAsync
あるため、で同じことを行うことはできません。UpdateUI
したがって、これはベストプラクティスにつながります。 ConfigureAwait(false)
「ライブラリ」async
メソッドで使用します。