01. C# Async/Await/Task Explained (Deep Dive). (Channel “Raw Coding”).
“In this tutorial we conver the asynchronous programming style in C# we take a deep diving looking at the state machine that the async keyword spawns. How the await keyword creates checkpoints in the state machine. And how the Task class allows us to bridge our code to use the asynchronous programming model.”
02. How to use Async/Await/Task in C#. (Channel “Raw Coding”)
“In this tutorial we take a look at how to use async, await and Task in C#. Primarily looking at good practices and how to avoid common pitfalls such as creating unecessary state machines, blocking threads, using ConfigureAwait when making libraries and how to avoid async in constructors.”
Related videos
03. Semaphore Explained C#.
In this Semaphore tutorial, I answer the questions: what is semaphore? what is semaphore used for? how to use semaphore? We go over a quick analogy to understand what the semaphore does and how to use it. We then look at a real world example of how it can be used to solve problems caused by asynchronous programming.
04. C# Channels Explained (System.Threading.Channels).
In this c# channels tutorial I answer the questions: what is a channel? how does a channel work? how to use a channel? when to use a channel? what problem does a channel solve?
Contents:
1. Basic problem that would require shared state to improve.
2. Simple custom implementation of channels.
3. Real World Example of Channels in ASP.NET Core
Links on the Channel subject:
• An Introduction to Channels in C#. Jeremy Bytes
• Channel
Class (Namespace: System.Threading.Channels
)
• Channel<T>
Class (Namespace: System.Threading.Channels
)
Asynchronous and synchronous wrappers
• Should I expose asynchronous wrappers for synchronous methods?
•• “If a developer needs to achieve responsiveness or parallelism with synchronous APIs, they can simply wrap the invocation with a method like
Task.Run
.”• Should I expose synchronous wrappers for asynchronous methods?
•• In the case of
async
/await
, this typically means making sure that any awaits inside of the asynchronous implementation you’re calling are using ConfigureAwait(false) on all await points; this will prevent the await from trying to marshal back to the current SynchronizationContext. As a library implementer, it’s a best practice to always use ConfigureAwait(false) on all of your awaits, unless you have a specific reason not to; this is good not only to help avoid these kinds of deadlock problems, but also for performance, as it avoids unnecessary marshaling costs.•• The simplest way to do that is to invoke the asynchronous work from the ThreadPool, such as by wrapping the invocation in a
Task.Run
, e.g.• How to safely mix sync and async code? [duplicate]
Task.Run
continues on the same thread causing deadlockhttps://stackoverflow.com/questions/46492823/task-run-continues-on-the-same-thread-causing-deadlock
Task.Wait
and “Inlining” (Optimization)https://devblogs.microsoft.com/pfxteam/task-wait-and-inlining/
Why is teaching this so hard? (“Don’t Block on Async Code”)
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html#comment-1fd877bd-6ec9-32d4-8c11-e21f10018d21
Parallel Computing – It’s All About the
SynchronizationContext
. By Stephen Cleary | February 2011. MSDN Magazine.https://learn.microsoft.com/en-us/archive/msdn-magazine/2011/february/msdn-magazine-parallel-computing-it-s-all-about-the-synchronizationcontext
How can I get a TaskScheduler for a Dispatcher?
https://stackoverflow.com/questions/6368885/how-can-i-get-a-taskscheduler-for-a-dispatcher
ConfigureAwait FAQ by Stephen Toub – MSFT
Task.Run Etiquette Examples: Don’t Use Task.Run in the Implementation by Stephen Cleary.
Good examples. But somewhat artificial.
In real applications the CPU-bounded operation may require to switch to UI thread to show progress.
.ConfigureAwait(false)
is not used, which is good in real applications, also considering inlining ofTask.Run
in such a cases.Simplified implementation of
static Task.WaitAsync
which is available in .NET 6.Note, synchronous
Task.Wait
is not used, because it blocks the thread even if it is run as lambda:await Task.Run(() => task.Wait())
Task.WhenAll
available for similar purposes. But it can’t be used with timeout or cancellation token. While the code above can be extended to support such features.How Async/Await Really Works in C# – Stephen Toub – MSFT
“The Result property is a blocking property. If you try to access it before its task is finished, the thread that’s currently active is blocked until the task completes and the value is available. In most cases, you should access the value by using
await
instead of accessing the property directly.”Source: Async return types (C#)
Understanding the Whys, Whats, and Whens of ValueTask
https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/
ValueTask Struct
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1