I currently have problems using async methods the right way. I may missunderstood something...
In my current project i have some async methods which should run in parallel, but they don't. So i created a small example project to reproduce the error.
class Program
{
static void Main(string[] args)
{
TaskAwaiter taskAwaiter = SomeParallelWork().GetAwaiter();
taskAwaiter.GetResult();
}
private static async Task SomeParallelWork()
{
Console.WriteLine(DateTime.Now + ": Start Parallel Work");
Task<string> task1 = HeavyDBWork(6000);
Task<string> task2 = HeavyDBWork(3000);
Task<string> task3 = HeavyDBWork(5000);
Console.WriteLine(DateTime.Now + ": All Parallel Work started");
await Task.WhenAll(new Task<string>[] { task1, task2, task3 });
Console.WriteLine(DateTime.Now + ": All Parallel Work done");
}
private static async Task<string> HeavyDBWork(int timeToWork)
{
Console.WriteLine(DateTime.Now + ": Start with heavy db work load: " + timeToWork);
await Task.Delay(timeToWork);
Console.WriteLine(DateTime.Now + ": End of heavy db work load: " + timeToWork);
return "SomeReturnValue";
}
}
The output is as i would expect it to be:
20.03.2020 10:50:28: Start Parallel Work
20.03.2020 10:50:28: Start with heavy db work load: 6000
20.03.2020 10:50:28: Start with heavy db work load: 3000
20.03.2020 10:50:28: Start with heavy db work load: 5000
20.03.2020 10:50:28: All Parallel Work started
20.03.2020 10:50:31: End of heavy db work load: 3000
20.03.2020 10:50:33: End of heavy db work load: 5000
20.03.2020 10:50:34: End of heavy db work load: 6000
20.03.2020 10:50:34: All Parallel Work done
All Tasks are generated first and then running in parallel. But this is not what i experienced in my project...
so i extended my example with some more "real" work: A recursive fibonacci algorithm
class Program
{
static void Main(string[] args)
{
TaskAwaiter taskAwaiter = SomeParallelWork().GetAwaiter();
taskAwaiter.GetResult();
}
private static async Task SomeParallelWork()
{
Console.WriteLine(DateTime.Now + ": Start Parallel Work");
Task<long> fibuTask = CPUWork(40);
Task<string> task1 = HeavyDBWork(6000);
Task<string> task2 = HeavyDBWork(3000);
Task<string> task3 = HeavyDBWork(5000);
Console.WriteLine(DateTime.Now + ": All Parallel Work started");
await Task.WhenAll(new Task<string>[] { task1, task2, task3 });
await Task.WhenAll(new Task<long>[] { fibuTask });
Console.WriteLine(DateTime.Now + ": All Parallel Work done");
}
private static async Task<string> HeavyDBWork(int timeToWork)
{
Console.WriteLine(DateTime.Now + ": Start with heavy db work load: " + timeToWork);
await Task.Delay(timeToWork);
Console.WriteLine(DateTime.Now + ": End of heavy db work load: " + timeToWork);
return "SomeReturnValue";
}
private static async Task<long> CPUWork(int i)
{
Console.WriteLine(DateTime.Now + ": Start Fibu of " + i);
long fibu = Fibu(i);
Console.WriteLine(DateTime.Now + ": End Fibu of " + i);
return await Task.FromResult<long>(fibu);
}
private static long Fibu(int i)
{
if(i==1||i==2)
{
return (long)1;
} else
{
return Fibu(i-2) + Fibu(i - 1);
}
}
}
Output:
20.03.2020 10:56:09: Start Parallel Work
20.03.2020 10:56:09: Start Fibu of 40
20.03.2020 10:56:10: End Fibu of 40
20.03.2020 10:56:10: Start with heavy db work load: 6000
20.03.2020 10:56:10: Start with heavy db work load: 3000
20.03.2020 10:56:10: Start with heavy db work load: 5000
20.03.2020 10:56:10: All Parallel Work started
20.03.2020 10:56:13: End of heavy db work load: 3000
20.03.2020 10:56:15: End of heavy db work load: 5000
20.03.2020 10:56:16: End of heavy db work load: 6000
20.03.2020 10:56:16: All Parallel Work done
Now the Fibunacci Sequence task is not just created first, it is some how await before the other tasks are created. I would expect the code to created all task and run them in parallel. What did i wrong?
Thanks for your answers!
Answer:
Thanks to Johnathan, Lasse and Theodor i was able to fix my code example.
So the new example executes three fibunacci algorithms asynchronously.
class Program
{
static void Main(string[] args)
{
TaskAwaiter taskAwaiter = SomeParallelWork().GetAwaiter();
taskAwaiter.GetResult();
}
private static async Task SomeParallelWork()
{
Console.WriteLine(DateTime.Now + ": Start Parallel Work");
Task<long> fibuTask1 = CPUWork(45);
Task<long> fibuTask2 = CPUWork(40);
Task<long> fibuTask3 = CPUWork(40);
Console.WriteLine(DateTime.Now + ": All Parallel Work started");
//await Task.WhenAll(new Task<string>[] { task1, task2, task3 });
await Task.WhenAll(new Task<long>[] { fibuTask1, fibuTask2, fibuTask3 });
Console.WriteLine(DateTime.Now + ": All Parallel Work done");
}
private static async Task<string> HeavyDBWork(int timeToWork)
{
Console.WriteLine(DateTime.Now + ": Start with heavy db work load: " + timeToWork);
await Task.Delay(timeToWork);
Console.WriteLine(DateTime.Now + ": End of heavy db work load: " + timeToWork);
return "SomeReturnValue";
}
private static async Task<long> CPUWork(int i)
{
Console.WriteLine(DateTime.Now + ": Start Fibu of " + i);
Func<long> fibuFunc = () => Fibu(i);
Task<long> fibuTask = Task.Run(fibuFunc);
long fibu = await fibuTask;
Console.WriteLine(DateTime.Now + ": End Fibu of " + i);
return fibu;
}
private static long Fibu(int i)
{
if(i==1||i==2)
{
return (long)1;
} else
{
return Fibu(i-2) + Fibu(i - 1);
}
}
}
Output:
20.03.2020 11:59:39: Start Parallel Work
20.03.2020 11:59:39: Start Fibu of 45
20.03.2020 11:59:39: Start Fibu of 40
20.03.2020 11:59:39: Start Fibu of 40
20.03.2020 11:59:39: All Parallel Work started
20.03.2020 11:59:41: End Fibu of 40
20.03.2020 11:59:41: End Fibu of 40
20.03.2020 11:59:53: End Fibu of 45
20.03.2020 11:59:53: All Parallel Work done
Your CPUWork
method will actually run synchronously, even though it is declared as async
.
Async methods only return a Task
when the first await
is encountered, and Task.FromResult
just wraps a value in an already completed Task
, so using await
will just unwrap the value straight away and return it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.