提问者:小点点

重构异步等待并行处理


我还在学习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秒就可以完成。我如何重构我的代码来实现这一点?谢啦!


共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);
}

这里发生的是对的调用将开始执行该方法,一旦执行到达执行实际异步操作的第一个,将返回正在运行的任务并将其分配给firsthello。第二个也一样你好。然后等待两者完成并打印结果。

这个实现只是简化工作方式的一个例子。在实际代码中,您可能应该使用来等待所有正在运行的任务

匿名用户

>

  • 可以使用Task.WhenAll等待多个任务。/li> 而不是(async/await-何时返回任务vs void?):

    private static async Task SayHelloTwice()
    {
        var hellos = await Task.WhenAll(PrintTask(), PrintTask());
        Console.WriteLine(hellos[0]);
        Console.WriteLine(hellos[1]);
    }
    

  • 相关问题