-3

I have an async method that get data from a database:

private async Task getDataAsync()
{
    await getDataFromDatabaseAsync();
}

I have a contructor that uses this method, in this way:

public MyViewModel()
{
    Task.WhenAll(getDataAsync());
    //getDataAsync().ConfigureAwait(false);

    //next line of code
}

The only way that I get to avoid the applications isn't blocked is using one the two options, both seems to work fine. I can use WhenAll or I can use ConfigureAwait(false).

Another options it is calling the method getDataASync() inside a task, but I guess it is a worse option becase it takes more resources.

So I would like to know which is the differences between WhenAll and ConfigureAwait.

When I use WhenAll in this way, the line of code "next line of code" is run after the async method is finisihed or it will run before finish?

Thanks.

Álvaro García
  • 18,114
  • 30
  • 102
  • 193
  • Looks like you're just trying to get around the fact you can't call async code in a constructor. Much better to not do that and rework that code. – DavidG Jun 08 '18 at 11:02
  • Task.WhenAll() will run all passed task to completion. ConfigureAwait(false) will not sync with the syncronization context when the task is completed. – Marcus Höglund Jun 08 '18 at 11:08
  • `ConfigureAwait` is about the synchronisation context and has nothing to do with "blocking". You are mixing asynchronous programing with parallel execution here. It's not the same thing. `Task.WhenAll` takes some tasks and lets them run as long as it takes and comes back when all are done. `await` behaves like that with one task and `ConfigureAwait` just tells it which context to use. – Alexander Schmidt Jun 08 '18 at 11:10
  • Is this running in a STA? e.g. WPF Dispatcher? – Michal Ciechan Jun 08 '18 at 11:45
  • Possible duplicate of [Can constructors be async?](https://stackoverflow.com/questions/8145479/can-constructors-be-async) – JSteward Jun 08 '18 at 15:50

1 Answers1

2

There is a common misconception that when you make a method async, it will be actually executed asynchronously (i.e. on a separate thread). That is not the case: async and await are a means to synchronize already asnychronous code. If you have nothing that is executed on a separate thread, your async code will run fully synchronously to the end.

Since getDataAsync is executed on the same thread as the MyViewModel constructor, you can run into a deadlock, since the thread waits for itself. When you use ConfigureAwait, you can avoid this situation.

Whether you actually should do that is a different question. What you are actually doing with ConfigureAwait is to start the task and to allow the await to continue on a separate context (which can be on a separate thread). Apart from the fact that you are not even using await here, continuation in a different context can become a problem when you want to execute UI operations after the await.

If you want to be sure that you can wait for getDataAsync in your constructor, you can use Task.Run to force execution in the thread pool:

var getDataTask = Task.Run((Func<Task>)getDataAsync);
//Do something else
getDataTask.Wait();

Everything you execute between Task.Run and the Wait() can run during the execution of getDataAsync. Whether parallelism is actually worth it here depends on what else you do until the Wait().

What you are doing in the MyViewModel constructor is to finally synchronize all asynchronous operations and make the execution of the constructor synchronous. If you want to run that operation asynchronously, you would need to start another task to do it. So you should be really sure that beyond that point async is not required anymore. If it is, run the initialization on another async method, await getDataAsync() there and synchronize somewhere up the call chain.

Sefe
  • 13,731
  • 5
  • 42
  • 55
  • But in the constructor I can't use the await keyword. I am not sure if in the last versions of .net it is possible to do that, it could be an option for me because I could use a newer version. – Álvaro García Jun 08 '18 at 11:29
  • for that reason you should use Activation concept - have a Command (I assume you use them, since the class is called ViewModel) and execute it once ViewModel is displayed. Do not use that in constructor. – Krzysztof Skowronek Jun 08 '18 at 11:31