C# Async/Await/Task Explained (Deep Dive)

Raw Coding
15 Apr 202024:22

Summary

TLDRThis video script offers an in-depth exploration of asynchronous programming in C#, focusing on the concepts behind async and await rather than just their implementation. The presenter uses the analogy of making tea to explain how async operations work, highlighting the difference between synchronous and asynchronous tasks. The script delves into the technical aspects, such as the role of the task, the state machine created by async, and the checkpoints introduced by await. It aims to clarify the underlying mechanisms that allow for non-blocking code execution, making it easier for viewers to understand and utilize async/await effectively in their C# applications.

Takeaways

  • 😀 The presenter aims to clarify the concepts behind async/await in C# rather than just showing implementation.
  • 🔍 The video uses the analogy of making tea to explain asynchronous programming, emphasizing non-blocking operations.
  • 💡 It's highlighted that async/await allows for multitasking by freeing up the thread to do other work while waiting for external tasks to complete.
  • 🛠️ The script explains that once a task hits an await, it yields control back to the thread pool, allowing other tasks to run.
  • 🔄 The concept of a 'task' is introduced as a bridge between the state machine and the await checkpoints.
  • 📚 The async keyword is described as spawning a state machine, which is a key component of asynchronous programming.
  • 🔑 The await keyword is likened to checkpoints within the state machine, controlling the flow of execution.
  • 🖥️ The script provides insight into how the .NET runtime manages threads, emphasizing the role of the thread pool.
  • 🌐 It discusses how network operations are handled asynchronously, involving the operating system and network drivers.
  • 🔍 The presenter uses ILSpy to demonstrate how async methods are translated into a state machine by the compiler.

Q & A

  • What is the main focus of the video?

    -The main focus of the video is to explain the underlying concepts behind async and await in C#, rather than just the implementation.

  • Why does the presenter believe that understanding async/await can help with sleepless nights?

    -Understanding async/await can fill gaps in knowledge that might cause confusion or keep one awake at night, implying that it's a concept that can be puzzling if not fully grasped.

  • What analogy does the presenter use to explain async/await?

    -The presenter uses the analogy of making a cup of tea to explain async/await, where boiling water is a synchronous task and preparing the tea while the water is boiling is an asynchronous task.

  • How does the presenter describe the difference between synchronous and asynchronous operations?

    -The presenter describes synchronous operations as tasks that are completed by the same thread without waiting for external processes, while asynchronous operations allow the thread to be free to do other tasks while waiting for an external process to complete.

  • What is a 'task' in the context of the video?

    -In the context of the video, a 'task' is an object that represents an asynchronous operation and is the bridge between the state machine created by async and the await keyword.

  • What is a 'state machine' as explained in the video?

    -A 'state machine' in the video refers to the object that is created when a method is made asynchronous. It holds the state of the method across await calls.

  • What is the role of the 'await' keyword in asynchronous programming?

    -The 'await' keyword is used to pause the execution of the current method until the awaited task is completed, allowing other operations to run in the meantime.

  • How does the presenter demonstrate that a task can be completed by a different thread?

    -The presenter demonstrates that a task can be completed by a different thread by creating a long loop that runs in parallel while an asynchronous task is awaited, showing that the task can finish on a different thread while the loop is still running.

  • What is the purpose of the thread pool as explained in the video?

    -The thread pool manages the execution of tasks by distributing them across available threads, allowing for efficient use of system resources and preventing thread overload.

  • How does the presenter explain the concept of a state machine checkpoint?

    -The presenter explains that a state machine checkpoint is created by the await keyword, which divides the asynchronous method into parts that can be executed sequentially as different states of the state machine.

  • What does the presenter suggest is the key to understanding asynchronous programming?

    -The presenter suggests that understanding the task as a bridge between the state machine and the code, the async keyword as what spawns the state machine, and the await keyword as defining the checkpoints within the state machine is key to understanding asynchronous programming.

Outlines

00:00

🍵 Introduction to Async and Await

The speaker begins by introducing the topic of asynchronous programming in C# using the analogy of making a cup of tea. They explain that async/await is about handling tasks that take time without blocking the execution of other code. The presenter emphasizes the importance of understanding the underlying concepts rather than just the implementation. They set the stage for a deep dive into how async/await works, starting with the basics for those unfamiliar with the concepts, and promising to fill in knowledge gaps that might be causing confusion.

05:01

🔄 Transitioning to Asynchronous Code

The speaker illustrates the shift from synchronous to asynchronous code by continuing the tea-making analogy. They explain how, in synchronous code, you would have to wait for the water to boil before proceeding with other steps, whereas in asynchronous code, you can start the kettle and then immediately proceed to take out the cups and add tea, waiting for the water to boil in the background. The explanation includes the concept of a 'task' and the use of 'await' to pause the current method until the asynchronous operation is complete. The summary also touches on how asynchronous code propagates from the bottom up in a codebase.

10:03

🌐 Understanding the Underlying Mechanisms

The presenter delves into the mechanics of asynchronous programming by discussing the role of the task, the state machine, and the awaiter. They use the tea-making analogy again to explain how the computer can handle external processes in parallel, similar to how one can multitask in making tea. The explanation includes the concept of the thread pool and how it manages threads, allowing a thread to be free to do other work while waiting for an asynchronous operation to complete. The summary also includes a discussion on how the application resumes execution on a different thread once the asynchronous operation is done.

15:04

💻 Exploring the State Machine and Async/Await

The speaker provides a deeper look into the state machine generated by the async keyword and how the await keyword checkpoints within it. They use the analogy of boiling water and adding tea to explain how the state machine preserves state and allows the program to resume execution from where it left off. The explanation includes how the .NET runtime manages the state machine and how the thread pool resumes execution of the function on a different thread once the asynchronous operation is complete.

20:05

🔧 Practical Example and Further Explanation

The presenter provides a practical example of using async tasks with an HTTP client to fetch a webpage from Google, explaining how the thread pool manages thread execution. They discuss how the operating system schedules threads on different processors and how threads can jump between CPUs. The explanation reinforces the role of the thread pool in managing threads and how it hands them off to the processor for scheduling. The summary concludes with an invitation for viewers to engage with the content, ask questions, and look forward to future videos on the topic.

Mindmap

Keywords

💡async/await

Async/await is a pair of keywords in C# used to simplify asynchronous programming. 'async' allows a method to run asynchronously, while 'await' is used to pause the async method until a result is available. In the video, the presenter explains how understanding async/await can help developers write more efficient code that doesn't block the main thread while waiting for tasks to complete, such as making a cup of tea while the water is boiling.

💡Task

A 'Task' in C# represents an asynchronous operation and is the return type of methods that are marked with 'async'. It acts as a bridge between the state machine created by 'async' and the 'await' checkpoints. The video script uses the analogy of making tea to explain how a task can be started and then completed at a later time by potentially a different thread.

💡State Machine

The 'state machine' is an internal representation that the C# compiler creates when a method uses 'async'. It manages the control flow of asynchronous code, allowing it to pause and resume at different points. The video script describes how the state machine is generated by the compiler and how it handles the different stages of an asynchronous operation.

💡Thread Pool

A 'Thread Pool' is a cache of reusable threads that can be utilized to execute asynchronous tasks. The video script explains how the thread pool manages threads, allowing them to be used for other tasks while waiting for an asynchronous operation to complete, such as boiling water for tea.

💡Synchronous

Synchronous execution means that code is executed in a sequence, waiting for one operation to complete before starting the next. The video contrasts synchronous and asynchronous programming by showing how synchronous code would wait for the water to boil before proceeding with making tea.

💡Asynchronous

Asynchronous execution allows code to initiate an operation and then continue executing other code while waiting for the operation to complete. The video uses the example of boiling water for tea to illustrate how asynchronous programming can perform other tasks while waiting for the water to boil.

💡Await

'Await' is used in C# to pause the execution of an async method until a Task is completed. In the video, the presenter explains how 'await' acts as a checkpoint within the state machine, allowing the thread to be freed up to do other work while waiting for the task to complete.

💡.NET Runtime

The '.NET Runtime' is the environment in which .NET applications execute. The video script mentions that when an asynchronous method is called, the runtime handles the execution of the method, including the creation of the state machine and the management of threads.

💡Intermediary Language (IL)

Intermediary Language, or IL, is the low-level language that .NET compilers emit, which is then executed by the .NET Runtime. The video script discusses how the async keyword results in the generation of IL code that represents the state machine for asynchronous execution.

💡Checkpoint

A 'checkpoint' in the context of the video refers to the points in the code where the execution is paused using 'await'. These checkpoints define the different states of the state machine and determine where the method can resume after the awaited task is completed.

💡Thread

A 'thread' is the smallest sequence of programmed instructions that can be managed independently by a scheduler, which is typically a part of the operating system. The video script uses threads to explain how different parts of the asynchronous operation can run in parallel, such as making tea while the water is boiling.

Highlights

Introduction to async/await in C# with a focus on underlying concepts rather than just implementation.

Explanation of async/await using the analogy of making a cup of tea.

The difference between synchronous and asynchronous operations demonstrated with boiling water.

How to make tea asynchronously by using 'await' to pause and resume tasks.

The necessity of understanding the task, the bridge between the state machine and the await.

The role of the thread pool in managing and resuming tasks.

How the async keyword transforms a function into a state machine.

The importance of the 'await' keyword as a checkpoint within the state machine.

Explanation of how tasks are completed by different threads in parallel execution.

The concept of a state machine having multiple parts controlled by the 'await' keyword.

How the thread pool resumes execution of a function at a different thread.

The illustration of the state machine's transition through different states with each 'await'.

The impact of the async/await pattern on the generated intermediate language (IL) code.

How the state machine preserves state across asynchronous operations.

The role of the operating system in scheduling threads and the thread pool's role in managing them.

The practical demonstration of how threads can jump between CPUs.

Encouragement for viewers to apply the concepts learned to enhance their understanding and use of async tasks.

Transcripts

play00:00

welcome everyone today I'm gonna be

play00:01

covering a sink and a weight along with

play00:03

tasks in c-sharp and generally today I'm

play00:06

gonna be explaining about a sink and the

play00:08

weight and how it works so if you come

play00:11

to understand just async/await

play00:12

from any other programming language you

play00:15

may benefit here I've seen a lot of

play00:17

tutorials that explain the

play00:18

implementation rather than explaining

play00:21

really the underlying concepts behind a

play00:23

sink and weight so today I'm gonna be

play00:26

primarily focusing on how it really

play00:28

works rather than how to implement it

play00:31

okay so that will really let you

play00:33

understand it and hopefully fill some

play00:35

gaps in your knowledge which don't let

play00:37

you sleep at night okay and the reason I

play00:39

guess why you're actually watching this

play00:40

video is there are so many of the

play00:42

tutorials out there why are you still

play00:43

looking at tutorials right you want to

play00:45

know some but today we're gonna take a

play00:47

deep dive and we're gonna start again if

play00:49

you don't know anything we're gonna

play00:50

start with an analogy all these videos

play00:52

have an analogy and here is mine right

play00:54

we're gonna make it be making cup of tea

play00:56

make a cup of tea you need to boil the

play00:58

kettle take the cups out put the tea in

play01:01

the cups and then put the boiled water

play01:03

in the cups right simple well let's see

play01:07

to make the tea

play01:08

we first need to boil the water this

play01:13

will give us some water good so then we

play01:19

take the cups out we dump them and then

play01:25

put tea in cup all right and then we

play01:32

pour let's say we pour our water and

play01:40

cups

play01:46

this will give us our tea and then we'll

play01:50

be able to return tea hey a couple of

play01:54

simple steps

play01:55

now the boiling water part this is the

play01:57

part where we press the button on an

play01:59

external thing to me so when I'm doing

play02:02

something I am completely synchronous I

play02:05

may have a couple of multiple threads

play02:06

that may put me in in a delusion that I

play02:10

feel like I'm multitasking but not

play02:12

really right oh boy water start the

play02:16

kettle and then we want to delay for two

play02:23

seconds our our kettle is really fast we

play02:26

boil in two seconds right we want to get

play02:28

a waiter get results to make this

play02:31

perform synchronously this is where

play02:35

we're waiting for the kettle we dump it

play02:41

and then get all finished boiling and we

play02:51

want to return water okay so let's go

play02:55

ahead and run this let's see what

play02:56

happens

play02:57

cool so starting the quatre kettle

play03:01

waiting for the kettle kettle finished

play03:02

boiling take the cups out but the team

play03:05

cups and pour water in cups how could

play03:08

this be better how well I'm a human

play03:10

being I'm no way am I gonna wait for the

play03:13

kettle to boil before I take the cups of

play03:15

tea out and put the tea in them right so

play03:18

something I do at the same time right

play03:21

because the kettle is external to me it

play03:23

can work while I'm doing another thing

play03:25

right I don't think I am NOT the kettle

play03:27

there's a key difference here and this

play03:29

is exactly how the computer does

play03:30

whenever it's something external to the

play03:33

process itself it can go work on its own

play03:35

it doesn't need to wait for it okay so

play03:37

this is the whole thing behind a

play03:38

synchrony so let's go ahead and make

play03:40

this asynchronous I'm going to copy this

play03:43

these two functions boil water async and

play03:48

we'll do make tea async as well

play03:53

sink so here instead of get a way to get

play03:58

a result we're gonna put a weight here

play04:00

and we will need to do a sync task so

play04:06

what's gonna happen here is once the

play04:09

thread is executing here it's gonna once

play04:11

it hits a weight it's gonna let up

play04:13

control it's gonna basically the thread

play04:15

is gonna get go free and it's gonna go

play04:16

do something else

play04:17

and then the thread pool is basically

play04:19

once it receives a signal that this

play04:21

delay is over it's gonna pick another

play04:24

threat to resume the task okay but we're

play04:26

gonna take a look at how that works in a

play04:28

little bit later but let's go ahead and

play04:29

finish working this example so oil water

play04:33

we actually want to call boil water

play04:35

async now and what we get is a task this

play04:39

is a boiling water task okay and what we

play04:43

actually want to do is once we have

play04:45

finished putting T in our cups we want

play04:48

to get the water by awaiting boiling

play04:52

water okay and again for this we'll need

play04:56

to make this an asynchronous task and

play04:58

we're just gonna go over what task is in

play05:00

a second okay and one thing to notice is

play05:06

once we go the asynchronous path we are

play05:08

no longer allowed to have asynchronous

play05:12

just in one sort of place it propagates

play05:15

through our our code from the bottom up

play05:17

up up and up to the main okay and again

play05:21

this is something that we'll need to

play05:23

make Anna synchronous tasks and the way

play05:28

so let's go ahead and run this cool

play05:32

right so start the kettle a wait for the

play05:36

kettle so we're waiting for the kettle

play05:38

here take the cups out put 10 cups we

play05:42

wait for the kettle to finish boiling

play05:43

and pour water and cups so we have

play05:46

successfully achieved a synchrony for

play05:48

boiling the water what's the next step

play05:51

well the next step is actually

play05:52

understanding what the [ __ ] is actually

play05:54

going on right so we have the task we

play05:59

have a sink and we have a wait we have

play06:01

three components to really understand

play06:03

the task

play06:05

is the bridge between the state machine

play06:08

that async creates and the weight is the

play06:12

checkpoints within your state machine

play06:15

once so this is a really my elevator

play06:20

pitch of this whole asynchronous

play06:22

programming right if you know how to use

play06:26

this and you've been using this for a

play06:27

while that whole sentence might have

play06:29

cleared everything up for you otherwise

play06:31

if you don't know about the state

play06:34

machine or you don't understand what I

play06:35

mean by a weight is a checkpoint let's

play06:37

go ahead and dive deeper so what's going

play06:40

to happen if I want to make the water

play06:45

finish boiling before I put the tea in

play06:48

the cups right so somewhere in the

play06:50

middle here let's go ahead and prove

play06:54

that another thread is indeed going to

play06:58

complete the water boiling process right

play07:00

so it's going to happen in parallel on

play07:02

another thread okay so vari let's go

play07:08

ahead and make a for loop really really

play07:17

big loop and in here we are going to

play07:24

just add I to eight or this amount of

play07:27

time so now this is a really really long

play07:30

loop what I'm gonna do is I'm also going

play07:31

to reduce the amount of time it takes

play07:33

for my kettle to boil and yeah let's go

play07:36

ahead and run this and this is what

play07:38

we're gonna see now so you can see there

play07:40

is no waiting here this thread is

play07:42

working full-time its throttling it's

play07:44

going through this loop like right but

play07:47

what has happened is when we have take

play07:50

the cups out the kettle has finished

play07:52

boiling while we were spinning around in

play07:54

one place maybe we'll praying over the

play07:55

dog whatever kettle finished boiling and

play07:58

it finished on a different thread okay

play08:00

and then we can put the tea in the cups

play08:03

and then we grab the result from that

play08:05

hurt right right because we can't we

play08:07

just have the water here so

play08:09

with that knowledge how does the

play08:13

application figure out how to make a

play08:16

different thread resume execution within

play08:20

this function right it's a function that

play08:23

essentially we've gone through the half

play08:25

of it and we kind of went well we have a

play08:28

week let's exit it right and then while

play08:31

we were still working here we resumed

play08:34

execution in this function what happened

play08:37

right what is going on for this I'm

play08:40

gonna take a little bit more of a

play08:41

realistic example of how we use threads

play08:45

right so let's go ahead and get some

play08:48

visibility on these threads so we're

play08:50

gonna be grabbing the current thread and

play08:52

we're just gonna be outputting the

play08:55

managed ad and we're just gonna dump it

play08:57

and we're gonna have a couple of

play09:03

processes the first one we're gonna

play09:06

create a client and it's going to be an

play09:08

HTTP client wrong place new HTTP client

play09:13

once we have the HTTP client let's

play09:16

actually create some work that we need

play09:19

to do we need to do right so a task and

play09:21

we're going to get string async and

play09:25

we're going to go to Google okay so in

play09:32

between here I'm gonna do the same thing

play09:34

I'm just gonna throw all this thread a

play09:35

little bit

play09:37

okay

play09:39

now I want to get the page I want to get

play09:41

the page from the task right because

play09:43

we're going to Google I want to wait on

play09:46

the task and I want to actually get the

play09:48

page so let's run this everything runs

play09:51

on one thread so this is what's going to

play09:54

happen here once we get the water it's

play09:57

still going to be running on the same

play10:00

thread this task is actually completed

play10:02

by a different thread okay so the way we

play10:06

can do this is we can reduce a couple of

play10:08

zeros on this loop and we can run this

play10:10

and we will see that the the rest of

play10:12

this function is now completed by a

play10:14

different thread okay so how does this

play10:17

work and this is something that the

play10:19

thread pool allows us to do so for this

play10:21

I'm gonna bring in the imagery that I

play10:24

have drawn I'm a bit of an artist myself

play10:26

so here we have the main on the main

play10:30

right our our program that we have just

play10:32

written right here and it's not just

play10:34

that the computer takes our program in

play10:36

executing our program sits in the.net

play10:39

runtime the.net process is being started

play10:41

and it's kind of this harness that our

play10:43

program is sitting in so our code runs

play10:48

this but when we issue the getstring

play10:52

async what actually happens is we go to

play10:58

the operating system and we're telling

play11:01

it we need to make an internet call we

play11:05

need to make an a call to the internet

play11:06

and this is where the operating system

play11:08

is gonna basically say right oh let me

play11:11

go to this network driver so depending

play11:14

on what computer you have you're gonna

play11:15

have a different operating system and

play11:17

different network drivers right so this

play11:19

needs to be like an abstract concept

play11:20

that we just call a function on an

play11:23

operating system and then the operating

play11:26

system is gonna have a specific driver

play11:27

for a specific network card and it's

play11:29

gonna call the specific function okay

play11:31

the network driver people the people who

play11:34

implement the network driver have to

play11:36

implement the correct function for it to

play11:38

be able to operate with the opera the

play11:40

Windows operating system and vice versa

play11:42

for other operating systems oh yeah when

play11:45

we scheduled this task when we say we

play11:48

need to make a network call

play11:51

so this is something that happens

play11:53

synchronously it make the operating

play11:56

system makes a call to the network

play11:58

driver and it says go get me this page

play12:00

but it also gives it an async flag so

play12:03

what the async flag does is basically

play12:06

the network driver frees controller the

play12:09

thread that called it okay so the so we

play12:13

don't get the controller thread back

play12:16

from a operating system perspective it's

play12:19

the network driver that basically says

play12:21

ma'am off you go right you're free to go

play12:23

and then once we return to step three I

play12:28

don't know exactly if when we return to

play12:32

step three but while we resume execution

play12:35

of our code the network driver is gonna

play12:39

send off the request and is gonna he's

play12:41

gonna try to get the page right so while

play12:45

he is getting the page we are throttling

play12:47

through this loop we're like right

play12:49

spinning her out and then we get to step

play12:51

four and this is where the magic happens

play12:53

right this is where the split and

play12:55

threads hop and threads happen this is

play12:58

where thread one basically flies off and

play13:00

goes there's something else this is

play13:02

where when we await the application

play13:06

basically goes over here to a thread

play13:09

pull the thing that manages your dotnet

play13:12

threads and it asks it you know this

play13:15

tasks though the the way scheduled is a

play13:17

complete and the thread is gonna and the

play13:20

thread pool is gonna go no it's not and

play13:22

this is when we basically we don't block

play13:25

the thread here either the thread that

play13:28

was running that process this function

play13:31

returns to the thread pool and the

play13:34

thread pool can use that thread for

play13:35

something else while this is as I said

play13:37

this is sleeping so now that we know

play13:41

that this thread has gone away and it's

play13:43

doing something else how do we return to

play13:48

finish off this function

play13:51

well once the network driver gets its

play13:55

data back it wakes up it goes like huh

play13:58

dude you know that task you asked for

play14:02

here it is take and then the thread pool

play14:05

goes oh okay this function carry on

play14:10

running okay and we complete the

play14:13

function so the next thing to understand

play14:17

is how can the task pool essentially

play14:22

stop in the middle of the function and

play14:25

then resume execution at a different

play14:27

thread how's that possible

play14:29

the next thing to understand is

play14:31

essentially the async keyword spawns the

play14:34

state machine so if I run this code

play14:35

right here here's some intermittent

play14:38

language that the common language

play14:41

runtime it uses to run as soon as we add

play14:45

a sync keyword it will bluster the

play14:50

amount of code generated and essentially

play14:52

we get this code explosion which is the

play14:54

state machine okay so what I'm alluding

play14:58

to is that this function is no longer a

play15:00

function it becomes an object which is

play15:02

the state machine right which sits in

play15:04

the dotnet runtime so let's go ahead

play15:08

peek into this state machine and take a

play15:12

look at what it's made of

play15:13

hey for this I'm gonna go into visual

play15:16

studio and here essentially I'll have

play15:19

this little example where I have the H

play15:22

the same example so I have the HDTV

play15:24

client I call Google I have the loop

play15:27

I await on that call then I have the

play15:29

page and then I'll put hello world okay

play15:32

so what I'm gonna be using here is

play15:34

called I else pipe basically take a look

play15:37

at the code at the intermittent language

play15:39

generated code for this function but in

play15:42

its readable format so the first thing

play15:43

to notice is that this main function is

play15:45

now an object right it's no longer a

play15:48

function once an object

play15:51

and it's fields are httpclient the task

play15:55

now we're

play15:58

turning here basically the variables in

play16:00

the function I've turned to a fields on

play16:03

the object right so it's some state that

play16:05

is going to be preserved on this state

play16:07

machine a and the primary function where

play16:11

basically the things that we do with our

play16:14

variables is now but in to move next and

play16:18

it's check pointed by the awake keyword

play16:21

okay so when I say check point at what

play16:25

I'm trying to do know is that here we

play16:28

have the first part of our code and once

play16:31

we pass the awake keyword we have the

play16:34

second part and every subsequent awake

play16:37

keyword we get an additional part to we

play16:40

give an additional part to the state

play16:41

machine to which it can jump on or an

play16:43

additional state that the state machine

play16:44

can be in okay so back to the IL code

play16:49

let's go ahead and take a look at the

play16:50

move next function this is how we change

play16:53

the state as a state machine and this is

play16:55

how we move through the parts move next

play16:57

function what I want to take what I want

play16:59

to bring your attention to are these

play17:02

parts so the first part is this if

play17:04

statement where we initialize the

play17:06

httpclient we get the string acing this

play17:09

is where we make the call to the network

play17:11

adapter we do our while loop and then we

play17:15

check if the task is completed right

play17:17

let's forget about this first and go to

play17:19

the step where everything is executed in

play17:21

one thread if we go past this we skip

play17:24

this else because it's out of scope and

play17:28

we get there waiter that we set here and

play17:30

we get the page we then clear the waiter

play17:34

and we output hello world right

play17:37

so here the await right here these two

play17:42

parts are part two okay so part one part

play17:46

two you can see that the page is being

play17:48

set here

play17:49

this is where part two begins and where

play17:52

the loop ends that's where part one ends

play17:54

hey so if it's not complete this is

play17:56

where we plain out just returned from

play17:58

the function but before we return we

play18:00

make sure to set some State on the state

play18:02

machine so what I want you to understand

play18:05

is that when we create the state machine

play18:07

we put it in memory and RAM right here

play18:11

somewhere

play18:12

and it's not garbage collected so the

play18:14

next so when we have this call that's

play18:17

going back to our thread pool the way it

play18:20

resumes it is the thread pool can find

play18:22

the state machine and memory and then

play18:24

just call the function move next again

play18:26

and because the state is now set to zero

play18:29

the number is not going to be zero we're

play18:32

going to essentially skip it right here

play18:34

we're gonna enter this clause and this

play18:37

is where we're just basically again

play18:39

we're gonna get the result of the await

play18:41

err because now we don't need to check

play18:44

if it's complete

play18:45

we know it's complete because the thread

play18:47

pool has triggered this call okay and at

play18:50

that point we go past this and we set

play18:53

the result and the task is complete our

play18:55

program finishes okay and that's pretty

play18:58

much it now what I want to do is I

play19:01

essentially I want to add another

play19:02

checkpoint so here let's go ahead turn

play19:05

this to a wait here and instead of page

play19:09

we're gonna have task two and we're

play19:11

still gonna have hello world so

play19:14

splitting this into parts it will be

play19:18

something like this first part second

play19:20

part third part okay let's go ahead and

play19:23

take a look at what gets generated now

play19:25

because it's gonna be slightly different

play19:27

and it's gonna be quite interesting so

play19:32

let's take a look at I'll spy

play19:37

we want to find open go okay so in here

play19:44

find async/await program main

play19:47

okay so again all the variables are here

play19:50

so just the task task - a HTTP client

play19:54

good and now these are just strings

play19:56

right and so looking into the move next

play20:00

what we get now are the two waiters that

play20:02

we potentially want to store and what I

play20:04

want to do here is essentially recreate

play20:07

or get an understanding of where these

play20:09

parts are again okay so we're gonna

play20:12

enter here we're gonna skip this first

play20:15

if statement because basically what I'm

play20:17

looking for is this HTTP client right

play20:19

because that's the first thing that we

play20:21

have defined I know that's the first

play20:22

thing that's gonna get executed so we

play20:25

have the HTTP client and then we go to

play20:28

the network card and we say go get us

play20:31

something it's not gonna be completed so

play20:33

we set the state we return next time we

play20:36

come back I want to look for this task

play20:40

being completed so the task that we're

play20:41

setting here is a waiter - so let's go

play20:45

ahead and look for a waiter - somewhere

play20:47

here in the bottom here we're grabbing

play20:49

the waiter - from the state we're

play20:52

getting the result getting the task

play20:54

setting some parameters we're looping

play20:57

and then we're doing the second call and

play21:01

again this is again when we return out

play21:03

of part two this is where part two

play21:04

finishes hey after we've done the

play21:07

looping we exit so third time when we

play21:10

come back right when the second network

play21:13

card call goes to the thread boom right

play21:14

I know I just got you this page

play21:18

right again we move for next and we can

play21:21

take note of where we exited here we set

play21:24

the stake to one so this is where the

play21:26

stake machine uses go to statements and

play21:29

through the move next it equals one yeah

play21:31

it's not zero if one yep this is where

play21:34

we go we get the ax waiter and again

play21:36

this is the waiter that we've set

play21:37

previously before exiting as the state

play21:40

machine we go to this label here and we

play21:42

can see that it's this label down here

play21:44

and this is where we again get the

play21:46

result of the a waiter because we

play21:48

already know it's complete because the

play21:49

thread pull knows it we don't need to

play21:51

check that is complete and we output

play21:54

hello world so this is where we execute

play21:56

the third part and I apologize this is

play21:58

probably a little bit something like

play21:59

this in terms of parts yeah so that's

play22:02

pretty much how I interpret the task as

play22:06

the bridge between the state machine and

play22:08

your code async is what spawns the state

play22:11

machine so you need the task to

play22:12

interface with it and then you have the

play22:14

await as in terms of how many parts do

play22:17

you have to your state machine how many

play22:20

times is it gonna get called again okay

play22:22

one thing I wanted to maybe clear up if

play22:26

you're not sure how we were actually

play22:29

executing in parallel when we were

play22:31

throttling right here right

play22:33

because what we have is in my task

play22:36

manager for example I have 4 cores 4

play22:38

cores that can execute if for example on

play22:42

this first core that I'm hovering over

play22:44

I've been doing the loop the insanely

play22:46

long loop so it's throttling through

play22:48

here but the task that's gonna get

play22:50

picked up the thread pool it's not gonna

play22:53

wait for this first processor to finish

play22:54

it's gonna take this thread pull and

play22:56

it's gonna throw it to the operating

play22:57

system and the operating system is then

play22:59

going to schedule it on the correct

play23:01

processor so the operating system is

play23:03

taking care of the heavy lifting the

play23:05

thread pull is just basically takes care

play23:08

of regulating how many threads you have

play23:10

and basically handing them off to the

play23:13

processor and the processor does the

play23:14

scheduling on your CPU and also while

play23:17

your thread is executing because all

play23:21

threads are all are allocated a certain

play23:22

amount of time on the CPU what actually

play23:25

can happen is that the thread can

play23:27

execute on one CPU for a long time so

play23:29

let's say this takes 2 seconds to run

play23:31

for the

play23:32

second it's gonna execute on this CPU

play23:34

and then for the second second it's

play23:37

gonna execute on a different CPU right

play23:39

so threads are not bound to a CPU they

play23:42

can jump between CPUs and just

play23:44

understand that the thread pool is what

play23:47

manages these threads okay so hopefully

play23:51

this was a good enough explanation of

play23:53

the async task and a wait hopefully you

play23:56

understand it a little bit more now if

play23:59

you do and you did enjoy this video

play24:00

leave a like subscribe if you have any

play24:03

questions make sure to leave them in the

play24:04

comment section don't forget to join the

play24:05

discord server I'm gonna make another

play24:07

video on how to actually use the async

play24:10

tasks and maybe give you a little bit

play24:12

more understanding of the potential that

play24:14

you can achieve with these if this video

play24:16

hasn't already done that yeah thank you

play24:18

for watching and hopefully I'll see you

play24:20

in my other videos

Rate This

5.0 / 5 (0 votes)

関連タグ
Asynchronous ProgrammingC# TutorialConcurrency ConceptsState MachineTask ManagementAwait ExplainedThread Pool.NET RuntimeCode OptimizationProgramming Fundamentals
英語で要約が必要ですか?