В настоящее время у меня проблемы с использованием правильных методов asyn c. Я могу что-то неправильно понять ...
В моем текущем проекте у меня есть несколько асин c методов, которые должны работать параллельно, но они этого не делают. Поэтому я создал небольшой пример проекта для воспроизведения ошибки.
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";
}
}
Вывод такой, какой я ожидал:
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
Сначала создаются все задачи, а затем выполняются в параллельно. Но это не то, что я испытал в своем проекте ...
, поэтому я расширил свой пример еще более "реальной" работой: рекурсивный алгоритм Фибоначчи
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);
}
}
}
Вывод:
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
Теперь задача «Последовательность Фибоначчи» не просто создается первой, но и ожидает того, как будут созданы другие задачи. Я ожидал бы, что код создаст все задачи и выполнит их параллельно. Что я не так?
Спасибо за ваши ответы!
Ответ:
Благодаря Джонатану, Лассе и Теодору я смог исправить свой код пример.
Таким образом, новый пример выполняет три алгоритма Фибуначи асинхронно.
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);
}
}
}
Вывод:
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