81

次の Windows フォームのコードを検討してください。

private async void UpdateUIControlClicked(object sender, EventArgs e)
{
    this.txtUIControl.Text = "I will be updated after await - i hope!";
    await Task.Delay(5000).ConfigureAwait(continueOnCapturedContext: false);
    this.txtUIControl.Text = "I am updated now.";
}

ここでは、待機後にコードが非 UI スレッドで実行されるため、3 行目で例外がスローされます。ConfigureAwait(false) はどこで役立ちますか?

4

2 に答える 2

120

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_ClickUI コンテキストで開始され、 が呼び出されDownloadFileAsyncます。DownloadFileAsyncも UI コンテキストで開始されましたが、呼び出しによってそのコンテキストからステップアウトしましたConfigureAwait(false)。残りはDownloadFileAsyncスレッド プール コンテキストで実行されます。ただし、DownloadFileAsync完了してDownloadFileButton_Click再開されると、UI コンテキストで再開されます。

経験則として、コンテキストが必要であるConfigureAwait(false)ことがわかっていない限り、使用することをお勧めします。

于 2015-01-08T23:32:31.327 に答える