Search code examples
c#async-awaittask-parallel-librarysynchronizationcontextconfigureawait

Task-Like and ConfigureAwait(false), is it possible?


I've been reading about task-like and awaitable types. I think I've got a good grasp on the basic mechanics of it (awaiter, asyncmethodbuilder...) but there's something amiss when I try to understand the usage of ConfigureAwait(false) in such scenario (if that is even possible).

My questions are:

Is ConfigureAwait reserved for "true" Tasks, meaning the usage or not of the SynchronizationContext?

If so, and say you're coding a general purpose library that exposes it's own implementations of task-like types, should you just use ConfigureAwait(false) when your code encounters Tasks?

Thanks.


Solution

  • If the task-like types of your library does not capture the context when awaited, then the users of your library will not be able to do this:

    private async void Button_Click(object sender, EventArgs e)
    {
        string input = Textbox1.Text;
        TaskLike<string> taskLike = YourLibrary.ProcessAsync(input);
        string result = await taskLike;
        Label1.Text = result // InvalidOperationException: Cross-thread operation not valid
    }
    

    On the other hand if the task-like types of your library always capture the synchronization context when awaited, then your library will be inefficient as a building block of other libraries, and will require from the other libraries authors to jump through hoops in order to invoke your library in a synchronization-context-free manner. So making your task-like types configurable regarding capturing the synchronization context should be a desirable feature.

    Regarding whether you should use ConfigureAwait(false) when the internal code of your library encounters standard Tasks, it depends on whether your library accepts caller-supplied lambdas. If for example your library includes a method like this:

    public TaskLike<string> ProcessAsync(Action action);
    

    ...then invoking the action after awaiting internally something with ConfigureAwait(false) may result to cross-thread violation exceptions, if the caller's lambda includes thread-affine code like reading properties of UI controls. To solve this problem may require to introduce a configuration parameter continueOnCapturedContext in the method's signature. At least this is the solution chosen by the Polly library.