19

I've done a bit of reading, and think I have grasped the basics of the await and async keywords, with regards to System.Threading.Task.

I'm not sure if I'm right over a small issue, however, and am looking for verification or for someone to correct me.

I'm implementing an async method, with this signature:

public Task ProcessUploadedFile(FileInfo info, string contentType);

Obviously, if I want to await anything inside the method, I need to add the async keyword into the signature,

My question is this: If the last thing that my method does is call another async method, or return a task, is there any point in awaiting it?

Eg.

1:

public async Task ProcessUploadedFile(FileInfo info, string contentType)
{
  foreach (var something in someCollection)
    DoSomething();

  DoSomethingElse();

  await DoMethodAsync();
}

2:

public Task ProcessUploadedFile(FileInfo info, string contentType)
    {
      foreach (var something in someCollection)
        DoSomething();

      DoSomethingElse();

      return DoMethodAsync();
    }

I initially wrote the former, but can no longer see the point in adding the await. If I were to write the latter, I accomplish the same thing, and the caller of both methods can still use the await keyword if they choose, no?

Is there any difference in the above? Which is "better"?

dark_perfect
  • 1,458
  • 1
  • 23
  • 41

1 Answers1

18

await is used to continue execution of method body when awaiting completed. If there is nothing to continue, then you don't need awaiting.

You can think of await (simplified) as of ContinueWith operation. So, your first method is something like:

foreach (var something in someCollection)
     DoSomething();

DoSomethingElse();

DoMethodAsync().ContinueWith(t => {});

There is nice MSDN article which describes what happens in async method which has nice code flow picture:

enter image description here

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • 1
    Wait. Can I just clarify something? In your rewritten version of my code, you have the DoSomething() and DoSomethingElse() in a Task.Factory.StartNew()...is that right? I thought these bits would run synchronously, on the same thread as the caller? And it would be DoMethodAsync().ContinueWith(t => {}_); ? – dark_perfect Aug 05 '13 at 16:14
  • 1
    @dark_perfect sorry, was in a rush. And yes, you are completely right. Updated code – Sergey Berezovskiy Aug 05 '13 at 20:35
  • 3
    You should also await when you want to catch exceptions from the async method even if you don't need to do anything afterwards. – Adi Lester Aug 05 '13 at 20:43
  • 2
    @Adi Even if I return the Task (instead of await), the caller of my method can still await the returned Task in order to catch the exception though, right? So in this case, it wouldn't make any difference, no? – dark_perfect Aug 05 '13 at 22:48
  • One more Thing to remember: IF you decide to turn away from 'async', a 'return null;' will be the Task then - so null! . So instead of leaving your code 1:1, you have to change value returns to an idiom like this: 'return Task.FromResult((XyClass)null);' - that is a fast task with a result already set. – Robetto Nov 09 '15 at 16:36