user2414460
user2414460

Reputation: 211

Understanding Async methods

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());
}

Upvotes: 0

Views: 172

Answers (4)

kidshaw
kidshaw

Reputation: 3451

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
});

Upvotes: 2

Stephen Cleary
Stephen Cleary

Reputation: 456322

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.

Upvotes: 2

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149518

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.

Upvotes: 1

PhillipH
PhillipH

Reputation: 6202

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

Upvotes: 2

Related Questions