When should I use ConfigureAwait(true)?

Viewed 41140

Has anyone come across a scenario for using ConfigureAwait(true)? Since true is the default option I cannot see when would you ever use it.

5 Answers

If you are using Azure's Durable Functions, then you must use ConfigureAwait(true) when awaiting your Activity functions:

string capture = await context.CallActivityAsync<string>("GetCapture", captureId).ConfigureAwait(true);

Otherwise you will likely get the error:

"Multithreaded execution was detected. This can happen if the orchestrator function code awaits on a task that was not created by a DurableOrchestrationContext method. More details can be found in this article https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-checkpointing-and-replay#orchestrator-code-constraints.".

Further information can be found here.

A situation to use ConfigureAwait(true) is when performing await in a lock, or using any other context/thread specific resources. This requires a synchronization context, which you will have to create, unless you are using Windows Forms or WPF, which automatically create a UI synchronization context.

In the following code (assumed to be called from the UI thread and synchronization context), if ConfigureAwait(false) was used, the locks would attempt to release on a different thread, causing an exception. This is a simple example that updates a large config file if it has changed from an external source, attempting to avoid write disk IO if the config file is the same as before.

Example:

/// <summary>
/// Write a new config file
/// </summary>
/// <param name="xml">Xml of the new config file</param>
/// <returns>Task</returns>
public async Task UpdateConfig(string xml)
{
    // Ensure valid xml before writing the file
    XmlDocument doc = new XmlDocument();
    using (XmlReader xmlReader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { CheckCharacters = false }))
    {
        doc.Load(xmlReader);
    }
    // ReaderWriterLock
    configLock.AcquireReaderLock(Timeout.Infinite);
    try
    {
        string text = await File.ReadAllTextAsync(ConfigFilePath).ConfigureAwait(true);

        // if the file changed, update it
        if (text != xml)
        {
            LockCookie cookie = configLock.UpgradeToWriterLock(Timeout.Infinite);
            try
            {
                // compare again in case text was updated before write lock was acquired
                if (text != xml)
                {
                    await File.WriteAllTextAsync(ConfigFilePath, xml).ConfigureAwait(true);
                }
            }
            finally
            {
                configLock.DowngradeFromWriterLock(ref cookie);
            }
        }
    }
    finally
    {
        configLock.ReleaseReaderLock();
    }
}
Related