alex.enjoy alex.enjoy - 2 months ago 28
C# Question

ToListAsync() does not complete at all

I want to execute some queries async.
But when I debug through the code, most times when an ToListAsync() is called the program stops.
There is no visible exception, and the callstack window is cleared.
When I press the pause button in VS, I can see the stack frame just before the current method was called.

var res1 = await context.Address().Where(...).ToListAsync();
var res2 = await context.Person().Where(...).ToListAsync();
var res3 = await context.Rule().Where(...).ToListAsync();


Sometimes the first call works, in rare cases the second too.
But at least at the third call the program stops.
I have absolutely no clue why...

Answer

From the comments:

It is a wpf application. The commands are within an async method. I call this from a non-async method using var result = LoadAsync.Result();

Right there, thats a deadlock. The DispatcherSynchronizationContext tries to marshal the continuation (everything after the first await) back onto the dispatcher (UI) thread, which is currently blocked by the call to LoadAsync.Result

The solution:

  1. await at the top of your call stack by making your method return an async Task instead of using Task.Result:

    await LoadAsync();
    
  2. If you absolutely cant change the method at the top of of the stack to async Task and for some obscure reason have to still call Task.Result, use ConfigureAwait(false) when awating your inner async methods. This will tell the sync context to explicitly not attempt to marshal work back to the dispatcher thread:

    var res1 = await context.Address().Where(...).ToListAsync().ConfigureAwait(false);
    var res2 = await context.Person().Where(...).ToListAsync().ConfigureAwait(false);
    var res3 = await context.Rule().Where(...).ToListAsync().ConfigureAwait(false);