3

I've read here that :

Await examines that awaitable to see if it has already completed; if the awaitable has already completed, then the method just continues running (synchronously, just like a regular method).

What ?

Of course it won't be completed because it hasn't even started !

example :

public async Task DoSomethingAsync()
{ 
  await DoSomething();
}

Here await examines the awaitable to see if it has already completed (according to the article) , but it (DoSomething) haven't event started yet ! , so the result will always be false

It would make sence if the article was to say :

Await examines that awaitable to see if it has already completed within x ms; (timeout)

I probably missing something here..

svick
  • 236,525
  • 50
  • 385
  • 514
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • 2
    You keep saying that the awaitable "hasn't started yet", but that's only an assertion/assumption in your question, not something you can point to in any documentation. – Damien_The_Unbeliever Jun 29 '13 at 12:29

2 Answers2

15

Consider this example:

public async Task<UserProfile> GetProfileAsync(Guid userId)
{
    // First check the cache
    UserProfile cached;
    if (profileCache.TryGetValue(userId, out cached))
    {
        return cached;
    }

    // Nope, we'll have to ask a web service to load it...
    UserProfile profile = await webService.FetchProfileAsync(userId);
    profileCache[userId] = profile;
    return profile;
}

Now imagine calling that within another async method:

public async Task<...> DoSomething(Guid userId)
{
    // First get the profile...
    UserProfile profile = await GetProfileAsync(userId);
    // Now do something more useful with it...
}

It's entirely possible that the task returned by GetProfileAsync will already have completed by the time the method returns - because of the cache. Or you could be awaiting something other than the result of an async method, of course.

So no, your claim that the awaitable won't have completed by the time you await it isn't true.

There are other reasons, too. Consider this code:

public async Task<...> DoTwoThings()
{
    // Start both tasks...
    var firstTask = DoSomethingAsync();
    var secondTask = DoSomethingElseAsync();

    var firstResult = await firstTask;
    var secondResult = await secondTask;
    // Do something with firstResult and secondResult
}

It's possible that the second task will complete before the first one - in which case by the time you await the second task, it will have completed and you can just keep going.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Was microsoft was so frustrated with `Task<..>` syntax that they decided to write this as a sugar syntax ?I mean its just like starting Tasks and inspecting the Result prop... – Royi Namir Jun 29 '13 at 19:30
  • @RoyiNamir: No, it's really not. It's a very long way from that. I suggest you take my async code at https://github.com/jskeet/DemoCode/tree/master/AsyncIntro and try rewriting it without `async`. You'll find it *much* more painful, I promise you. The compiler is doing an awful lot of work to remove boilerplate, error-prone code. – Jon Skeet Jun 29 '13 at 19:32
  • Jon, In your example you used "_downloading from a webservice_" -- an `IO` operation which probably supports asynchronous methods (e.g. beginXXX) -- so we don't want to block the thread while IO is in progress. **BUT** what if `DoSomething` would be just a method which calculates long fibonacci numbers ? even if we open a `Task` , it will waste _another_ thread to do the calculation. and so I ask , does the true benefit is for IO operations ? thank you. – Royi Namir Jul 01 '13 at 11:05
  • @RoyiNamir: For a compute-bound task you'd want to create a new task, probably on a thread-pool thread, e.g. with `Task.Run`. There's still a benefit there, in terms of getting back to the UI thread when it's completed. – Jon Skeet Jul 01 '13 at 11:47
4

await can take any Task or Task<T>, including completed tasks.

In your example, the inner DoSomething() method (that should rather be named DoSomethingAsync(), and its caller DoSomethingElseAsync()) returns a Task (or a Task<T>). That task can be a completed task fetched from somewhere else, the method is not required to start its own task.

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479