1

I've recently been learning asynchronous programming and I think I've mastered it. Asynchronous programming is simple just allowing our program to multitask.

The confusion comes with await and async of programming, it seemed to confused me a little more, could somebody help answer some of my concerns?

I don't see the async keyword as much, just something you chuck on a method to let Visual Studio know that the method may await something and for you to allow it to warn you. If it has some other special meaning that actually affects something, could someone explain?

Moving onto await, after talking to a friend I was told I had 1 major thing wrong, await doesn't block the current method, it simply executes the code left in that method and does the asynchronous operation in its own time.

Now, I'm not sure how often this happenes, but lets say yo have some code like this.

Console.WriteLine("Started checking a players data.");

var player = await GetPlayerAsync();

foreach (var uPlayer in Players.Values) { 
    uPlayer.SendMessage("Checking another players data");
}

if (player.Username == "SomeUsername") { 
    ExecuteSomeOperation();
}

Console.WriteLine("Finished checking a players data.");

As you can see, I run some asynchronous code on GetPlayerAsync, what happens if we get deeper into the scope and we need to access player, but it hasn't returned the player yet?

If it doesn't block the method, how does it know that player isn't null, does it do some magic and wait for us if we got to that situation, or do we just forbid ourselves from writing methods this way and handle it ourselves.

H H
  • 263,252
  • 30
  • 330
  • 514
Jan Edan
  • 69
  • 6
  • U want to check if the player is null or not ? – Software Dev Mar 15 '18 at 18:06
  • And if it isn't? I guess you're screwed? – Jan Edan Mar 15 '18 at 18:06
  • what exactly do u want ? if u want to check the value of the player, then i assume u can do something like `If (player.Value == null)` ( i dont know what properties ur player has but if it has a `value `property it might work) – Software Dev Mar 15 '18 at 18:08
  • 4
    "Asynchronous programming is simple just allowing our program to multitask." [No, asynchrony and parallelism are two very different things.](https://stackoverflow.com/questions/23833255/does-using-tasks-tpl-library-make-an-application-multithreaded/23833635#23833635). Asynchronous programming is when an operation returns immediately, and does some work after having returned, possibly with a means of notifying a caller when the underlying operation has actually finished. It is the opposite of doing thing synchronously. That has nothing to do with parallelism. – Servy Mar 15 '18 at 18:10
  • `async` on a method will turn it into a state machine that runs code after `await`s as continuations. Also it's required if you want to use `await`. – juharr Mar 15 '18 at 18:10

4 Answers4

14

I've recently been learning asynchronous programming and I think I've mastered it.

I was one of the designers of the feature and I don't feel like I've even come close to mastering it, and you are asking beginner level questions and have some very, very wrong ideas, so there's some hubris going on here I suspect.

Asynchronous programming is simply just allowing our program to multitask.

Suppose you asked "why are some substances hard and some soft?" and I answered "substances are made of arrangements of atoms, and some atom arrangements are hard and some are soft". Though that is undoubtedly true, I hope you would push back on this unhelpful non-explanation.

Similarly, you've just replaced the vague word "asynchronous" with another vague word "multitask". This is an explanation that explains nothing, since you haven't clearly defined what it means to multitask.

Asynchronous workflows are undoubtedly about executing multiple tasks. That's why the fundamental unit of work in a workflow is the Task<T> monad. An asynchronous workflow is the composition of multiple tasks by constructing a graph of dependency relationships among them. But that says nothing about how that workflow is actually realized in software. This is a complex and deep subject.

I don't see the async keyword as much, just something you chuck on a method to let Visual Studio know that the method may await something and for you to allow it to warn you.

That's basically correct, though don't think of it as telling Visual Studio; VS doesn't care. It's the C# compiler that you're telling.

If it has some other special meaning that actually affects something, could someone explain?

It just makes await a keyword inside the method, and puts restrictions on the return type, and changes the meaning of return to "signal that the task associated with this invocation is complete", and a few other housekeeping details.

await doesn't block the current method

Of course it does. Why would you suppose that it does not?

It doesn't block the thread, but it surely blocks the method.

it simply executes the code left in that method and does the asynchronous operation in its own time.

ABSOLUTELY NOT. This is completely backwards. await does the opposite of that. Await means if the task is not complete then return to your caller, and sign up the remainder of this method as the continuation of the task.

As you can see, I run some asynchronous code on GetPlayerAsync, what happens if we get deeper into the scope and we need to access player, but it hasn't returned the player yet?

That doesn't ever happen.

If the value assigned to player is not available when the await executes then the await returns, and the remainder of the method is resumed when the value is available (or when the task completes exceptionally.)

Remember, await mean asynchronously wait, that's why we called it "await". An await is a point in an asynchronous workflow where the workflow cannot proceed until the awaited task is complete. That is the opposite of how you are describing await.

Again, remember what an asynchronous workflow is: it is a collection of tasks where those tasks have dependencies upon each other. We express that one task has a dependency upon the completion of another task by placing an await at the point of the dependency.

Let's look at your workflow in more detail:

var player = await GetPlayerAsync();
foreach (var uPlayer in Players.Values) ...
if (player.Username == "SomeUsername") ...

The await means "the remainder of this workflow cannot continue until the player is obtained". Is that actually correct? If you want the foreach to not execute until the player is fetched, then this is correct. But the foreach doesn't depend on the player, so we could rewrite this like this:

Task<Player> playerTask = GetPlayerAsync();
foreach (var uPlayer in Players.Values) ...
Player player = await playerTask;
if (player.Username == "SomeUsername") ...

See, we have moved the point of dependency to later in the workflow. We start the "get a player" task, then we do the foreach, and then we check to see if the player is available right before we need it.

If you have the belief that await somehow "takes a call and makes it asynchronous", this should dispel that belief. await takes a task and returns if it is not complete. If it is complete, then it extracts the value of that task and continues. The "get a player" operation is already asynchronous, await does not make it so.

If it doesn't block the method, how does it know that player isn't null

It does block the method, or more accurately, it suspends the method.

The method suspends and does not resume until the task is complete and the value is extracted.

It doesn't block the thread. It returns, so that the caller can keep on doing work in a different workflow. When the task is complete, the continuation will be scheduled onto the current context and the method will resume.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • If `async` only enables `await` and puts restrictions on return type, is it possible to remove `async` from `async Task Execute() {return 2;}`? :) – Karol Mar 16 '18 at 20:35
  • @Karol: Good point, I neglected the trivial case. I'll amend the text. – Eric Lippert Mar 16 '18 at 20:36
  • I thank you deeply for writing this, it really did clear it up for me, thanks! – Jan Edan Mar 19 '18 at 06:21
  • @EricLippert can you please provide some link references for asnyc await blogs which you have authored or some good blogs you know. I want to know more about async await. – Rudresha Parameshappa Mar 20 '18 at 11:32
3

await doesn't block the current method

Correct.

it simply executes the code left in that method and does the asynchronous operation in its own time.

No, not at all. It schedules the rest of the method to run when the asynchronous operation has finished. It does not run the rest of the method immediately. It's not allowed to run any of the rest of the code in the method until the awaited operation is complete. It just doesn't block the current thread in the process, the current thread is returned back to the caller, and can go off to do whatever it wants to do. The rest of the method will be scheduled by the synchronization context (or the thread pool, if none exists) when the asynchronous operation finishes.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • Great explanation! Two things though: a) I think that agreeing with the first quote --*that `await` doesn't block the current **method***-- might be a little bit misleading (although you clarify later that what it doesn't block is the current ***thread***). b) I think it would be more helpful if you include your comment above (about asynchrony vs parallelism) as part of the answer. – 41686d6564 stands w. Palestine Mar 16 '18 at 19:47
1

I had 1 major thing wrong, await doesn't block the current method, it simply executes the code left in that method and does the asynchronous operation in its own time.

But it does block the method, in the sense that a method that calls await won't continue until the results are in. It just doesn't block the thread that the method is running on.

... and we need to access player, but it hasn't returned the player yet?

That simply won't happen.

async/await is ideal for doing all kinds of I/O (file, network, database, UI) without wasting a lot of threads. Threads are expensive.

But as a programmer you can write (and think) as if it were all happening synchronously.

H H
  • 263,252
  • 30
  • 330
  • 514
-4

In this code, you will not use Await because GetPlayerAsync() runs some asynchronous code. You can consider it from the perspective that Async and Await are different in that "Async" is waiting while "Await" operates asynchronously.

Try to use Task< T > as return data.

Robert Columbia
  • 6,313
  • 15
  • 32
  • 40
Amine Moh
  • 1
  • 2