I wanted to learn how async works in c# and found some basic examples that base on Task.Delay. They work fine and code like this works as expected:
static int taskNo = 0;
static async Task<Task> test(int k)
{
int _taskNo = ++taskNo;
Console.WriteLine($"Started task {_taskNo}");
await Task.Delay(1000 * k);
Console.WriteLine($"Finished task {_taskNo}");
return Task.CompletedTask;
}
static async Task Main(string[] args)
{
Task[] tasks = new Task[3];
tasks[0] = test(4);
tasks[1] = test(3);
tasks[2] = test(2);
await Task.WhenAll(tasks);
Console.WriteLine("All tasks finished.");
Console.ReadLine();
}
Originally I wanted to try making some big loops, like adding strings thousands of times, just to try it. Is it possible to do it async? When I try to use code like this, it just works on one thread (I can see just one thread working at 100%). How can I create multiple instances of that loop to work on every thread of the CPU?
//how to make this code to be able to work asynchronously?
static async Task LoopTest()
{
int _taskNo = ++taskNo;
Console.WriteLine($"Started task {_taskNo}");
string s = "";
for(int i = 0; i < 1000000; i++)
{
s += "qwertyuzxcvb";
}
Console.WriteLine($"Finished task {_taskNo}");
}
Edit: In one of the comments I asked how one thread can do operations faster than multiple threads, and here is the code, that I tested:
static int taskNo = 0;
static async Task LoopTest()
{
int _taskNo = ++taskNo;
Console.WriteLine($"Started task {_taskNo}");
string s = "";
for(int i = 0; i < 30000; i++)
{
s += "qwertyuzxcvb";
}
Console.WriteLine($"Finished task {_taskNo}");
}
static async Task Main(string[] args)
{
DateTime asyncStartTime = DateTime.Now;
Console.WriteLine($"Started async.");
// async
Task[] tasks = new Task[15];
Parallel.ForEach(tasks, (Task) => LoopTest());
DateTime asyncEndTime = DateTime.Now;
taskNo = 0;
//sync
DateTime syncStartTime = DateTime.Now;
Console.WriteLine($"Started sync.");
for(int i = 0; i < tasks.Length; i++)
{
LoopTest();
}
DateTime syncEndTime = DateTime.Now;
TimeSpan asyncTimeSpan = asyncEndTime - asyncStartTime;
TimeSpan syncTimeSpan = syncEndTime - syncStartTime;
Console.WriteLine($"Async finished in {asyncTimeSpan}, sync finished in {syncTimeSpan}.");
Console.ReadLine();
}
I can see that when async starts, all threads are pinned to 100% (this is i7 9750H, 12 threads are working, it says 100% CPU usage), and once it gets to sync, just one thread is pinned to 100% and overall CPU usage says 25%. Maybe there is just some dumb mistake, but how can it be faster in sync?
Btw, I know that it's pretty stupid example for async and I know that there are many benefits in other situations, but I just wanted to do that looping test and now I just have more and more questions...