使用 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
在两种情况下很有用:
- 提高 GUI 应用程序的响应能力。
- 提高服务器应用程序的可伸缩性。
这些似乎都不是您的情况,因此没有理由在您的代码中使用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