Search code examples
c#.netwpfmultithreadingdispatcher

C# - Dispatcher.InvokeAsync ContinueWith not awaited


Assuming ChartViewModels is an ObservableCollection<T>, the following code works as expected:

await Dispatcher.InvokeAsync(() =>
{
    ChartViewModels.Clear();
    ChartViewModels.AddRange(initializedCharts);
}, DispatcherPriority.DataBind, mCancellationToken.Token);

await UpdateChartsWithValuesAsync(chartsToInitialize, ChartViewModels).ConfigureAwait(false);

Instead, if I wrap the the UpdateChartsWithValuesAsync method call in the ContinueWith delegate, the method is not awaited anymore. I already tried to change the ConfigureAwait(false) to true but nothing seems to change. Below the edited code:

await Dispatcher.InvokeAsync(() =>
{
    ChartViewModels.Clear();
    ChartViewModels.AddRange(initializedCharts);
}, DispatcherPriority.DataBind, mCancellationToken.Token).Task
.ContinueWith(async t => await UpdateChartsWithValuesAsync(chartsToInitialize, ChartViewModels).ConfigureAwait(false), mCancellationToken.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current).ConfigureAwait(false);

The code into the Dispatcher is always executed before the ContinueWith delegate, but it doesn't await UpdateChartsWithValuesAsync to complete anymore, raising nasty bugs.

Can anyone explain this behaviour? Thanks

WPF, .NET Framework 4.7 project


Solution

  • Simply put, .ContinueWith() does not do await in its implementation, instead runs the passed in delegate as it is and returns a Task of Task (Task<Task>>). This outer task, because not awaiting on the passed in delegate, completes immediately.

    What I suggest, don't use .ContinueWith() in this case, simply stick to await. If you really keen to keep the current code, you can do .ContinueWith().Unwrap(), what will does the trick.

    Also here is an another related question in the topic: Use an async callback with Task.ContinueWith

    If you wanna learn more in depth, the source code of ContinueWith: https://referencesource.microsoft.com/#mscorlib/system/threading/tasks/Task.cs,4532