Stephen Cleary には、これに関する非常に優れたシリーズがあります。ここで見つけることができます。あなたの質問に固有の部分を引用しました。
ほとんどの場合、「メイン」コンテキストに同期する必要はありません。ほとんどの非同期メソッドは、構成を念頭に置いて設計されます。これらは他の操作を待機し、それぞれが非同期操作自体を表します (他の操作で構成できます)。この場合、 ConfigureAwaitを呼び出して を渡すことで、現在のコンテキストを取得しないように awaiter に指示します。たとえば、次のようになります。false
private async Task DownloadFileAsync(string fileName)
{
// Use HttpClient or whatever to download the file contents.
var fileContents = await DownloadFileContentsAsync(fileName).ConfigureAwait(false);
// Note that because of the ConfigureAwait(false), we are not on the original context here.
// Instead, we're running on the thread pool.
// Write the file contents out to a disk file.
await WriteToDiskAsync(fileName, fileContents).ConfigureAwait(false);
// The second call to ConfigureAwait(false) is not *required*, but it is Good Practice.
}
// WinForms example (it works exactly the same for WPF).
private async void DownloadFileButton_Click(object sender, EventArgs e)
{
// Since we asynchronously wait, the UI thread is not blocked by the file download.
await DownloadFileAsync(fileNameTextBox.Text);
// Since we resume on the UI context, we can directly access UI elements.
resultTextBox.Text = "File downloaded!";
}
この例で注意すべき重要なことは、非同期メソッド呼び出しの各「レベル」には独自のコンテキストがあるということです。DownloadFileButton_Click
UI コンテキストで開始され、 が呼び出されDownloadFileAsync
ます。DownloadFileAsync
も UI コンテキストで開始されましたが、呼び出しによってそのコンテキストからステップアウトしましたConfigureAwait(false)
。残りはDownloadFileAsync
スレッド プール コンテキストで実行されます。ただし、DownloadFileAsync
完了してDownloadFileButton
_Clickが再開されると、UI コンテキストで再開されます。
経験則として、コンテキストが必要であるConfigureAwait(false)
ことがわかっていない限り、使用することをお勧めします。