0

I have a method void getInformation() that calls 5 other methods of which each is getting some data from a database. It takes about 1 second until all data is collected and returned to getInformation() and because of that I thought I should collect the data in the background. My question is: can I just make getInformation() async so the UI isn't blocked while the other methods are collecting the information or do I have to make every of the other methods async ?

private void button_Click(object sender, EventArgs e)
{
  await getContactInformation();
}

public async Task getContactInformation()
{
  this.data.Add(collectData1());
  this.data.Add(collectData2());
  this.data.Add(collectData3());
  this.data.Add(collectData4());
  this.data.Add(collectData5());
}
Daniel Kelley
  • 7,389
  • 5
  • 41
  • 48
user2414460
  • 211
  • 2
  • 14
  • look into this [tutorial](http://www.dotnetperls.com/async) – Sagar Pilkhwal Sep 11 '14 at 10:37
  • 1
    Take a look at these Q&As: https://stackoverflow.com/questions/14177891/can-somebody-please-explain-async-await, https://stackoverflow.com/questions/10960998/how-different-async-programming-is-from-threads and https://stackoverflow.com/questions/14455293/async-and-await – Dirk Sep 11 '14 at 10:43

5 Answers5

2

In general I would recommend all IO to be taken off the UI thread, but there is no point in making each individual call async.

For guidance on the effect of async calls on database IO blocked threads, I found this very clear and useful advice.

http://blogs.msdn.com/b/rickandy/archive/2009/11/14/should-my-database-calls-be-asynchronous.aspx

AlexanderBrevig
  • 1,959
  • 12
  • 17
PhillipH
  • 6,031
  • 1
  • 14
  • 25
2

No. Your method body has to use an await or you'll get a warning.

Easy enough.

Wrap your method body with...

await Task.Run(()=>{
// do your thing
});
Daniel Kelley
  • 7,389
  • 5
  • 41
  • 48
kidshaw
  • 3,221
  • 2
  • 14
  • 25
2

First off, the ideal situation for async is to use "async all the way". In this case, your code would look like this:

private async void button_Click(object sender, EventArgs e)
{
  await getContactInformationAsync();
}

public async Task getContactInformationAsync()
{
  this.data.Add(await collectData1Async());
  this.data.Add(await collectData2Async());
  this.data.Add(await collectData3Async());
  this.data.Add(await collectData4Async());
  this.data.Add(await collectData5Async());
}

Note that modern database APIs such as Entity Framework 6, ADO.NET, SQLite, etc, all have asynchronous APIs that you can use to implement the collectDataNAsync methods. This is the ideal async scenario, since it minimizes thread waste and also keeps the UI nicely responsive.

However, if you want more of a "quick fix", then you can push the (synchronous) calls off to a background thread, and then treat that background work asynchronously, as such:

private async void button_Click(object sender, EventArgs e)
{
  await Task.Run(() => getContactInformation());
}

public void getContactInformation()
{
  this.data.Add(collectData1());
  this.data.Add(collectData2());
  this.data.Add(collectData3());
  this.data.Add(collectData4());
  this.data.Add(collectData5());
}

This would solve your immediate problem (freeing up the UI thread) at the expense of a thread pool thread. It's not ideal but it would work.

Stephen Cleary
  • 406,130
  • 70
  • 637
  • 767
1

Purpose of async Task is to let it execute in background without locking the main thread, such as doing a DownloadFileAsync. The basic idea is that you have a separate pool of threads that execute tasks asynchronously. When using it. The object does however make the promise that it will execute the operation at some time and give you the result when you request it. This means that it will block when you request the result and hasn't finished, but execute in the thread pool otherwise.

The only difference between async and a synchronous one is that we can do something (such as write a message) after the async method starts. It avoids blocking control flow. Statements continue as normal. Async and await are a code pattern—they allow methods to asynchronously run. They make code that uses threads easier to read. And this in turn makes that code less prone to flaws.

http://blogs.msdn.com/b/cdndevs/archive/2013/12/18/c-async-and-await-why-do-we-need-them-part-1.aspx

How and When to use `async` and `await`

Finally

Programs are full of methods that do not immediately return. Sometimes an external slowdown, as from a network, is the cause, not processor usage. With async and await, we run methods asynchronously—threads are optional.

Community
  • 1
  • 1
Sagar Pilkhwal
  • 5,914
  • 2
  • 27
  • 78
1

can I just make getInformation() async so the UI isn't blocked while the other methods are collecting the information or do I have to make every of the other methods async ?

The latter. When you go async it is "async all the way", meaning you make async method calls all the way to the top of your stack. For IO bound operations, there isn't a need to use background threads, since most APIs these days expose XXXAsync method calls which are truely asynchronous, which means your UI message loop is free to process other messages while the IO request executes.

An important thing to note though is that marking a method async is not enough to make it asynchronous. You actually have to await an async operation, such as your database method call. If there's no async API call to your database, you wont be able to go async.

In you case, getContactInformation will make the compiler omit a warning saying you have an async method which isn't being awaited. De-Facto, if you await getInformation(), you will be running completely synchronously.

Yuval Itzchakov
  • 141,979
  • 28
  • 246
  • 306
  • But if I want to make the data-collect-calls `async` too, I'd have to change my whole project. This code was just to get an idea on how to get a solution for this – user2414460 Sep 11 '14 at 12:05
  • The solution is to make your data-collect calls `async`. That is the primary point. If your DB calls are synchronous, how do you expect to make them async? – Yuval Itzchakov Sep 11 '14 at 12:21
  • I was hoping for a solution where I don't have to change all method- bodys and headers, something like `BackgroundClass.doInBackground(methodCall)`, that makes the UI responsive but still executes the called method. – user2414460 Sep 11 '14 at 12:26
  • You *can* do this using a background thread. But, that would be waisting a completely good thread which will simply block until the IO request completes. If you need this to scale-out eventually, that wont work. I would recommend you not to do that. I think it is worth the effort to refactor your codebase to support true asynchronous calls. – Yuval Itzchakov Sep 11 '14 at 12:28