Considérez le code suivant des formulaires Windows:
private async void UpdateUIControlClicked(object sender, EventArgs e)
{
this.txtUIControl.Text = "I will be updated after 2nd await - i hope!";
await Task.Delay(5000).ConfigureAwait(continueOnCapturedContext: false);
this.txtUIControl.Text = "I am updated now.";
}
Ici, l'exception est levée à la 3ème ligne car après attendre, le code est exécuté sur un thread non-UI. Où ConfigureAwait (false) est utile?
Stephen Cleary a une très bonne série sur ce que vous pouvez trouver ici , j'ai cité le morceau spécifique à votre question:
La plupart du temps, vous n’avez pas besoin pour vous synchroniser avec le contexte "principal". La plupart des méthodes asynchrones seront conçues avec une composition en tête: elles attendent d’autres opérations, et chacune d’elles représente une opération asynchrone elle-même (qui peut être composée par d’autres). Dans ce cas, vous voulez dire à l'attente pas capturer le contexte actuel en appelant ConfigureAwait et en passant
false
, par exemple: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!"; }
La chose importante à noter avec cet exemple est que chaque "niveau" d'appels de méthode async a son propre contexte.
DownloadFileButton_Click
A démarré dans le contexte de l'interface utilisateur et appeléDownloadFileAsync
.DownloadFileAsync
a également commencé dans le contexte de l'interface utilisateur, mais est sorti de son contexte en appelantConfigureAwait(false)
. Le reste deDownloadFileAsync
s'exécute dans le contexte du pool de threads. Cependant, lorsqueDownloadFileAsync
est terminé et queDownloadFileButton
_ Click reprend, il fait reprend dans le contexte de l'interface utilisateur.Une bonne règle est d'utiliser
ConfigureAwait(false)
à moins que vous ne vous connaissiez faites avez besoin du contexte.
Vous devez l’utiliser à tout moment dans les services, car ceux-ci doivent être agnostiques à l’interface utilisateur.
Cependant, ne l'utilisez pas en dehors des services si
Dans ces cas, vous ne devez pas utiliser ConfigureAwait(false)
car il est important de capturer le contexte actuel, sinon l'application plantera en essayant d'accéder aux vues d'interface utilisateur à partir d'un thread non-UI.
Lorsque vous écrivez await task;
, Cela équivaut à écrire wait task.ConfigureAwait(true);
. Si vrai est le défaut.