Async await
in C#
Why should we care?
- Thundering herd
- Horses = users
What is our goal
- Do more with less
- Juggle more users
How? An analogy
- Imagine a 'wash and fold' laundry business
- When people drop off clothes, you have a choice:
- Sync vs async
Sync (blocking)
- A customer arrives with clothes
- You put the clothes in the machine
- You sit in front of the machine until they are done
- You take the clothes back to the front desk
- You can now serve the next customer
Computer time
Async (non-blocking)
- A customer arrives with clothes
- You take their phone number and give them a ticket
- You put the clothes in the machine
- You go back to the desk to help the next customer
- When the clothes are done, you call the first customer
Apply the analogy
- Laundromat = your application
- Customer = request
- Employee = thread
- Washing clothes = calling an external service
- We want to be able to give people tickets, not sit and wait
Talk Outline
- Key concepts
- Best practices and common gotchas
- 5 take aways
What is a task?
- Think of a task like a laundry ticket
- You give it to the customer immediately
- When the items are ready, we'll tell you
- "An abstraction over an activity that is ongoing and will eventually complete." Mads Torgersen
What is await?
- Like the front desk
- Place to come back when the task is done
- Where we can resume execution for that customer
- Await does not mean 'wait'
Waiting is relative
- The customer still has to wait
- But the employee does not
- They can 'juggle' many customers
Is it faster?
- The total washing time is still an hour
- The user has to wait 1 hour plus service time
- This is still faster than sync approach of a queue
- In sync, your wait includes the washing time of other people
Threads
- It's like the employee
- One person can handle hundreds of customers because they do things concurrently
Parallel | Concurrent |
---|---|
Literally at the same time | Little slices, one after the other |
Parallel vs concurrent
Multithreading | Async await |
Hire more employees | Buy more washing machines |
I/O | CPU |
---|---|
Calling external service | Internal work |
I/O vs CPU
Async await helps here | Parallelization helps here |
Like the washing machine | Like folding clothes |
Calling DB, API, disk | Looping, calculation |
Summary (so far)
- Task is like a ticket
- Await is like the front desk
- Thread is like an employee
- We seem fast by doing this concurrently
Best practices
When I/O, then async
- Any time we call an external service
- E.g. file system, API, DB
- Use async await
Don't block
- Avoid methods like .Result() or .WaitAll() or .Wait()
- These will force the thread to sit in front of the washing machine
- This means async code will spread
Be suspicious of Task.Run
- This moves the work to another thread
- Like hiring another person
- If it's I/O they are still blocked - they still sit and wait for machine to finish
- Might be okay for CPU bound work but there are better ways to do parallelization
Avoid await inside a loop
Use list of tasks instead
Use .ConfigureAwait(false) for UI thread
- This allows ANY thread to resume the work, not the calling thread
- This is important for any applications with a UI
- Any laundromat employee can give your clothes back, not just the one who served you originally
- Dotnet core does not have this problem
5 take aways
- All I/O should be async
- Avoid blocking keywords
- Be suspicious of Task.Run
- Avoid await inside a loop
- Use .ConfigureAwait(false) for old UI work
Async await in C#
By Tom Dane
Async await in C#
An introduction to async await in C#
- 581