我还在学习C#,遇到了一个我需要帮助的问题。考虑以下代码:
private async Task<String> PrintTask()
{
await Task.Delay(3000);
return "Hello";
}
private async void SayHelloTwice()
{
string firstHello = await PrintTask();
string secondHello = await PrintTask();
Console.WriteLine(firstHello);
Console.WriteLine(secondHello);
}
现在SayHelloTwice()将需要6秒来完成。但是,我希望检索任务并行运行,这样只需要3秒就可以完成。我如何重构我的代码来实现这一点?谢啦!
正确的方法(没有死锁的风险)是使用
private async void SayHelloTwice()
{
string[] results = await Task.WhenAll(
PrintTask(),
PrintTask());
Console.WriteLine(results[0]);
Console.WriteLine(results[1]);
}
库编写者通常会努力使任务中的“回调”代码在调用它的原始线程上运行。这通常是因为只能从单个线程访问对象。
当使用诸如
但是,正如前面提到的,经常
因此,在第一种情况下,外部“任务”持有线程,并等待完成。
第二种情况,内部的“任务”正在等待线程完成。
因此,两者都无法完成。
通常,你想要的是开始两个任务,然后等待。一个直截了当的办法是:
private async void SayHelloTwice()
{
// Start the tasks, don't wait
Task<string> firstHello = PrintTask();
Task<string> secondHello = PrintTask();
// Wait for results
string firstResult = await firstHello;
string secondResult = await secondHello;
// Print results
Console.WriteLine(firstResult);
Console.WriteLine(secondResult);
}
这里发生的是对
这个实现只是简化工作方式的一个例子。在实际代码中,您可能应该使用
>
private static async Task SayHelloTwice()
{
var hellos = await Task.WhenAll(PrintTask(), PrintTask());
Console.WriteLine(hellos[0]);
Console.WriteLine(hellos[1]);
}