使用 async/await 来提高性能

本文关键字:高性能 await async 使用 | 更新日期: 2023-09-27 18:34:05

我目前有一个服务方法,它对传入的数据运行一组"规则"。其中一些规则执行简单的检查,例如验证 ID 号,还有一些规则会转到数据库以查找信息。它看起来很像这样:

public void RunRules(ValidationRequest request)
{
    // Each rule returns bool for this example
    var rules = GetRules();
    var results = List<bool>();
    Parallel.ForEach(rules, rule =>
    {
        var result = rule();
        lock(results)
            results.Add(result);
    });
    foreach(var result in results)
    {
        RecordResultInDatabase(result);
    }
    CallNextService(someNewRequest);
}

我认为(但不确定(我可以使用async/await来改进事情。我的想法是,当一个规则完成时,它可以在其他规则仍在运行时调用RecordResultInDatabase

但是,作为一项要求,我不希望在所有规则运行及其结果记录在数据库中之前调用CallNextService

问题是我是一个绝对的菜鸟async/await,我认为(但不确定(Task.WaitAll可能是我正在寻找的。

我非常不确定如何做到这一点,但我猜像这样的事情:

List<Task<bool>> ruleTasks = GetRules();
Task.WaitAll(ruleTasks);
// Somehow get the results of the rules and record them in the db???

使用 async/await 来提高性能

我不认为async - await会提高您情况下的性能。简而言之,async - await在两种情况下很有用:

  1. 提高 GUI 应用程序的响应能力。
  2. 提高服务器应用程序的可伸缩性。

这些似乎都不是您的情况,因此没有理由在您的代码中使用async - await

如果要在处理请求时调用RecordResultInDatabase(),而不是在所有请求都完成后调用请求,则可以使用 PLINQ 而不是 Parallel.ForEach() 。另一个好处是,它还将简化您的代码:

var results = GetRules().AsParallel().Select(rule => rule());
foreach (var result in results)
{
    RecordResultInDatabase(result);
}

你不是在等待/异步之后:这些旨在暂停GUI应用程序中方法的执行,同时防止GUI冻结,并提高服务器场景中的可伸缩性,因为它有时可以避免使用"线程"作为"等待"。由于您似乎没有等待异步操作,并且这不是GUI,因此这些都不适用于您。

调用服务的客户端可能会使用 await/async,但这是一个不同的问题。

您可以研究的是Task(并行任务库(。但前提是您的测试确实可以并行运行并且足够大,值得!对于微小、快速和简单的测试,并行运行它们可能会损害性能,而不是提高。

最后,由于这在服务器上运行,因此您需要考虑并发活动:服务器是否仅为此请求提供服务?除非这是真的,否则你根本不应该使用线程,保持单线程和干净。由于所有 CPU 线程都将占用为其他并发请求提供服务,因此运行多个任务或 ParallelLoop 只会损害性能,不仅对于此请求,而且对于同时运行的所有其他请求。这是因为没有"免费"内核来获取您的线程,但您确实请求它们。无需利用额外的 CPU 容量。你最终只是做了上下文切换(并为此付出代价(,而没有得到任何好处。

一如既往:测试,测试

,测试。

MSDN 上的任务类:http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx