I am trying to understand how async/await
work in C#. I created the below example.
public class SynchronizedCache<TKey, TValue>
{
private readonly System.Threading.ReaderWriterLockSlim _lock
= new System.Threading.ReaderWriterLockSlim();
private readonly IDictionary<TKey, TValue> _dictionary
= new Dictionary<TKey, TValue>();
public TValue this[TKey key]
{
get
{
_lock.EnterReadLock();
try
{
if (!_dictionary.TryGetValue(key, out var value))
{
throw new InvalidOperationException($"key {key} doesn't exist");
}
return value;
}
finally
{
_lock.ExitReadLock();
}
}
set
{
_lock.EnterWriteLock();
_dictionary[key] = value;
_lock.ExitWriteLock();
}
}
public bool TryGetValue(TKey key, out TValue value)
{
try
{
value = this[key];
return true;
}
catch (Exception)
{
value = default(TValue);
return false;
}
}
public void SetValue(TKey key, TValue value)
{
this[key] = value;
}
}
class Program
{
private static readonly SynchronizedCache<int, string> Cache
= new SynchronizedCache<int, string>();
private static readonly Random Random = new Random();
private static readonly IList<Task> Readers = new List<Task>();
private static readonly IList<Task> Writers = new List<Task>();
static async Task ReaderTask(string name)
{
while (true)
{
lock (Random)
{
var index = Random.Next(1, 100);
if (Cache.TryGetValue(index, out var value))
{
Console.WriteLine(
$"Reader({name} {Thread.CurrentThread.ManagedThreadId}"
+ $", cache[{index}]={value}");
}
}
await Task.Delay(1000);
}
}
static async Task WriterTask(string name)
{
while (true)
{
lock (Random)
{
var index = Random.Next(1, 100);
var value = Random.Next(100, 1000);
Cache[index] = value.ToString();
Console.WriteLine(
$"Writer({name}) {Thread.CurrentThread.ManagedThreadId}"
+ $", cache[{index}]={Cache[index]}");
}
await Task.Delay(500);
}
}
private static async Task Main(string[] args)
{
Console.WriteLine($"Main thread {Thread.CurrentThread.ManagedThreadId}");
await Task.WhenAll(
// readers
ReaderTask("Reader 1"),
ReaderTask("Reader 2"),
ReaderTask("Reader 3"),
ReaderTask("Reader 4"),
// writers
WriterTask("Writer 1"),
WriterTask("Writer 2"));
}
}
When I run the above code, I get the following output:
Main thread 1
Writer(Writer 1) 1, cache[80]=325
Writer(Writer 2) 1, cache[28]=550
Writer(Writer 2) 4, cache[95]=172
Writer(Writer 1) 5, cache[71]=132
Writer(Writer 2) 5, cache[67]=454
Writer(Writer 1) 5, cache[91]=314
Writer(Writer 2) 5, cache[39]=154
Writer(Writer 1) 5, cache[99]=921
Writer(Writer 2) 6, cache[56]=291
Writer(Writer 1) 5, cache[8]=495
Writer(Writer 2) 6, cache[74]=907
Writer(Writer 1) 5, cache[35]=101
Writer(Writer 2) 5, cache[11]=449
Writer(Writer 1) 6, cache[64]=932
Writer(Writer 2) 7, cache[34]=825
Writer(Writer 1) 5, cache[88]=869
Reader(Reader 1 4, cache[8]=495
Writer(Writer 2) 8, cache[43]=983
Writer(Writer 1) 6, cache[15]=590
Writer(Writer 2) 5, cache[22]=276
Writer(Writer 1) 6, cache[58]=845
I get that my Main()
thread is with ThreadId 1
but what I don't understand is where are the other threads created? I am not creating any specific threads here. Does calling an async function creates task that is already scheduled on a threadpool thread ?