繁体   English   中英

仅在任务并行库上使用异步/等待有什么好处?

[英]What are the benefits of using async/await over Task Parallel Library alone?

我知道这个问题可能有点琐碎,但是我在互联网上找到的所有答案都让我感到困惑。 我知道用怎样的基本原则async/await (如何作品await asynchroniously等待任务完成不阻塞主线程),但我不明白它的真正的好处,因为在我看来,一切与你做异步/ await您可以使用Task Paralel库进行操作。 请考虑以下示例,以更好地理解我的意思:假设我有一个SuperComplexMethod ,它返回一些值,并且我想并行执行它,同时做一些其他事情。 通常我会这样:

internal class Program
{
    private static void Main()
    {
        //I will start a task first that will run asynchroniously  
        var task = Task.Run(() => SuperComplexMethod());

        //Then I will be doing some other work, and then get the result when I need it
        Console.WriteLine("Doing some other work...");
        var result = task.Result;
    }

    static string SuperComplexMethod()
    {
        Console.WriteLine("Doing very complex calculations...");
        Thread.Sleep(3000);
        return "Some result";
    }
} 

在这里,我将如何使用async/await做到这一点:

internal class Program
{
    private static void Main()
    {
        var task = SuperComplexMethodAsync();

        Console.WriteLine("Doing some other work...");
        var result = task.Result;
    }

    //I have to create this async wrapper that can wait for the task to complete
    async static Task<string> SuperComplexMethodAsync()
    {
        return await Task.Run(() => SuperComplexMethod());
    }

    static string SuperComplexMethod()
    {
        Console.WriteLine("Doing very complex calculations...");
        Thread.Sleep(3000);
        return "Some result";
    }
}

如您在第二个示例中看到的那样,为了使用async/await方法,我必须创建一个包装器方法来启动任务并异步等待其完成。 显然,这对我来说似乎是多余的,因为无需使用标记为async/await包装器就可以实现相同的行为。

您能否解释一下async/await什么特别之处,以及与单独使用Task Parallel Library工具相比,它有什么实际好处?

可以说使用async / await的主要原因是线程备用 设想以下情形(我将简化为重点):a)您有一个Web应用程序,该应用程序具有10个可用于处理传入请求的线程; b)所有请求都涉及I / O(例如,连接到远程数据库,通过HTTP / SOAP连接到上游网络服务)以进行处理/完成; c)每个请求需要2秒钟来处理。

现在,假设大约有20个请求同时到达。 如果没有异步/等待,则您的Web应用程序将开始处理前10个请求。 发生这种情况时,其他10个队列将仅排队等待2秒钟,您的Web应用程序将耗尽线程,因此无法对其进行处理。 仅当前10个完成时,才开始处理后10个。

在异步/等待状态下,前10个请求将开始执行任务,并且在等待这些任务时,处理它们的线程将返回到Web应用程序以处理其他请求。 因此,您的Web应用将立即开始处理后10个,而不是等待。 随着前10个任务的完成,Web应用程序将继续在线程池线程或Web应用程序线程之一(取决于您如何配置事物)上处理其余方法。 通常,我们可以期望在I / O场景中I / O占调用持续时间的大部分,因此我们可以合理地假设,在上述场景中,网络/数据库调用可能需要1.9s的时间,并且其余代码(适应DTO,某些业务逻辑等)可能需要0.1秒。 如果我们假设继续(等待之后)是由Web应用程序线程处理的,那么该线程现在仅占用2秒中的0.1秒,而不是非异步/等待情况下的2秒。

您可能会自然地认为:好吧,我只是将线程从一个线程池中推出,然后推入另一个线程池中,并且最终也将填满。 要了解为什么在真正的异步场景中实际上并非如此,您需要阅读There is No Thread

结果是,您现在可以同时处理更多的请求,而没有可用的线程来处理它们。

您会注意到上面的内容集中在I / O上,而这正是异步/等待的亮点。 如果您的Web应用通过使用CPU执行复杂的数学计算来处理请求,则您将看不到上述好处,因此,为什么异步/等待并不真正适合也不适合与CPU绑定的活动一起使用。

在其他人加入规则的所有例外(还有一些例外)之前,我仅介绍一种简单的简化方案,以显示在I / O绑定方案中异步/等待的价值。 涵盖有关异步/等待的所有内容将创建一个很长的答案(而这个答案已经足够长了!)

我还应该补充一点,还有其他异步处理Web请求的方法,这些方法早于async / await,但是async / await大大简化了实现。

-

简短地讲一个WinForms或类似的应用程序,情况非常相似,除了现在您实际上只有一个线程可用于处理UI请求,并且每当您抓住该线程时,UI都将无响应,因此您可以使用将长时间运行的操作移出UI线程的类似方法。 在UI方案中,从UI线程执行与CPU绑定的操作也变得更加合理。 执行此操作时,线程池线程将代替该线程执行CPU工作,释放UI线程以保持UI响应。 现在一个线程,但至少它不是一个UI。 这通常称为“卸载”,这是异步/等待的其他主要用途之一。

-

您的示例是一个控制台应用程序-在那种情况下通常没有什么收获,除了能够相当容易地(可以说比创建自己的线程更容易)在线程池上同时执行多个请求的能力之外。

使用异步并等待编译器在后台生成状态机时

public async Task MyMethodAsync()
{
    Task<int> longRunningTask = LongRunningOperationAsync();
    // independent work which doesn't need the result of LongRunningOperationAsync can be done here

    //and now we call await on the task 
    int result = await longRunningTask;
    //use the result 
    Console.WriteLine(result);
}

public async Task<int> LongRunningOperationAsync() // assume we return an int from this long running operation 
{
    await Task.Delay(1000); // 1 second delay
    return 1;
}

所以这里发生了什么:

  1. 任务longRunningTask = LongRunningOperationAsync(); 开始执行LongRunningOperation

  2. 假设主线程(线程ID = 1)完成独立工作,然后等待长时间运行的任务。

现在,如果longRunningTask尚未完成并且仍在运行,则MyMethodAsync()将返回其调用方法,因此主线程不会被阻塞。 当longRunningTask完成时,来自ThreadPool的线程(可以是任何线程)将在其先前的上下文中返回MyMethodAsync()并继续执行(在这种情况下,将结果打印到控制台)。

第二种情况是longRunningTask已经完成其执行并且结果可用。 当到达await longRunningTask时,我们已经有了结果,因此代码将继续在同一线程上执行。 (在这种情况下,将结果打印到控制台)。 当然,对于上面的示例,情况并非如此,其中涉及Task.Delay(1000)。

有关更多信息,请参见:=>

异步/等待-最佳做法

简化异步

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM