async and await let a method stop waiting, give its thread back, and pick up where it left off when the work finishes. The method does not get its own thread, and marking something async does not make it faster.
Asynchronous programming is about not blocking a thread while you wait for something outside your process, usually a disk, a network or a database. Multithreading is about doing more than one piece of work at once on more than one core. They solve different problems and the articles below keep them apart.
A Task is a promise that a result will exist later. A Thread is an operating system resource. You almost always want the first one, and the framework decides whether a thread is even needed.
Once two things run at once you need to protect the data they share, so the later sections cover locking, the concurrent collections and how to cancel work that is already running.
Async and Await Fundamentals
What async actually does, and the comparisons that clear up most of the confusion.
- Thread.Sleep vs Task.Delay
- Difference Between await and Task.Wait
- Difference Between Asynchronous Programming and Multithreading
- Understanding Task and ValueTask
- Tasks vs Threads
- Using Task.CompletedTask, Task.FromResult and Return in C# Async Methods
Running and Combining Tasks
Starting work, waiting for several pieces of it, and the loop mistake that quietly makes everything serial.
- Difference Between Task.Run and Task.Factory.StartNew
- Parallel.ForEachAsync() and Task.Run() With When.All
- Why Should We Avoid Using Await in a Loop
- Short Circuit Evaluation of IF Statements with Await
- How to Execute Multiple Tasks Asynchronously
Async Streams and Cancellation
Producing results one at a time without blocking, and stopping work that is already in flight.
- IAsyncEnumerable with yield
- Cancellation Tokens with IAsyncEnumerable
- Persist Values With AsyncLocal in C# Async Flow
- How to Convert IAsyncEnumerable to List
Locking and Synchronization
Protecting shared state once more than one thread can reach it.
- Synchronization Mechanisms – Volatile vs Interlocked vs lock
- When to Use ReaderWriterLockSlim Over lock
- What is Locking and How to Use a Locking Mechanism
- Try-Catch Block
- Working With Semaphore Class in C# and Best Practices
- How to Use Mutex
Concurrent Collections and Threads
The collections built for concurrent access, and working with threads directly when you really do need to.
- ConcurrentQueue
- ConcurrentBag
- ConcurrentDictionary in C# – Detailed Guide
- Difference Between Returning and Awaiting a Task
- Concurrent Collections
- ConcurrentStack
- How to Run Code in a New Thread
Where to Go Next
Async code touches these topics constantly:
Never block on async code with .Result or .Wait(). Make the calling method async and await it. That one habit prevents most async deadlocks.
