C# .Net Asynchronous Coding
Provides ability to work with multiple threads
process ⇒ application
thread ⇒ smallest unit that can shared cpu time
Asynchronous Coding is NOT parallel programming
Many threads and few cores ⇒ lots of threads waiting
When you create a thread you are never sure when the thread will start or get processor time.
Getting threads from the OS is expensive.
Solution: app gets a 'thread pool' - threads in this pool are reused to save repeatedly getting threads from OS.
async
and await
- enable you to write asynchronous code, but do NOT create thread(s)
A useful property to check when working with threads is Environment.Current.ManagedThreadId
Creating Threads
Creating a new thread from the Thread Pool
var customers = await Task.Run(
async () =>
{
await
// do stuff
return customers;
}
);
Waiting for multiple threads to finish...
var task1 = Task.Run(async () => .... );
var task2 = Task.Run(async () => .... );
var result = Task.WhenAll(task1, task2);
Task.Run
takes from the thread pool -> not ideal as can run out of threads in the thread pool.
Can create threads manually:-
var thread = new Thread(async () => { actions });
// or for tasks that will task more than 0.4 seconds..
Task.Factory.StartNew( () => { your code here }, Task.CreateOptions.LongRunning )
async
AND await
Normally this is all done within the libraries you consume (e.g. ASP.Net), but you still need async
and await
to allow the framework to use the threads. e.g. in EFCore the Async
methods are handling their own threads.
Cannot await void
, can only await Task<..>
Manually "awaiting"
var thread = new Thread( () => { <code here>; result = ... }) {
IsBackground = true
};
thread.Start()
while (thread.IsActive) {};
return ask.FromResult(result);
This method is more powerful but also more complicated.
In ASP.Net await Task.Run
doesn't make sense. You're already in a thread and are stealing another thread from the thread pool.
Never create a thread and immediately await it in ASP.NET core.
await Task.Run
makes sense when in the main thread.
Using Task.Run
var result = Task.Run( () => { code here} );
// do other stuff
var x = await result();
Running several actions indepent of each other
var num1 = Task.Run( () => { ... code here... });
var num2 = Task.Run( () => { ... code here... });
var result = await Task.WhenAll(num1, num2);
return result.Sum();