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 lancée à la 3ème ligne car après l’attente, le code est exécuté sur le thread non-interface utilisateur. Où ConfigureAwait (false) est utile?
Stephen Cleary a une très bonne série à ce sujet, que vous pouvez trouver ici . J’ai cité l’article spécifique à votre question:
La plupart du temps, vous n’avez pas besoin de synchroniser avec le contexte «principal». La plupart des méthodes asynchrones seront conçues en fonction de la composition: elles attendent d’autres opérations et chacune représente une opération asynchrone elle-même (qui peut être composée par d’autres). Dans ce cas, vous voulez dire au serveur de ne pas capturer le contexte actuel en appelant ConfigureAwait et en transmettant
false
, par exemple:private async Task DownloadFileAsync(ssortingng 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» des appels de méthode asynchrone a son propre contexte.
DownloadFileButton_Click
démarré dans le contexte de l’interface utilisateur et appeléDownloadFileAsync
.DownloadFileAsync
également démarré dans le contexte de l’interface utilisateur, mais a ensuite quitté son contexte en appelantConfigureAwait(false)
. Le rest deDownloadFileAsync
s’exécute dans le contexte du pool de threads. Cependant, lorsqueDownloadFileAsync
termine et queDownloadFileButton
_Click est réactivé, il reprend dans le contexte de l’interface utilisateur.Une bonne règle à suivre est d’utiliser
ConfigureAwait(false)
sauf si vous savez que vous avez besoin du contexte.