1

我目前有一个对传入数据运行一组“规则”的服务方法。其中一些规则执行简单的检查,例如验证 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???
4

2 回答 2

4

我不认为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);
}
于 2013-10-07T09:24:38.287 回答
2

You're not after await/async: those are designed to suspend execution of a method in a GUI application while preventing the GUI from freezing, and to improve scalability in server scenarios because it can sometimes avoid using a "thread" for the "await". Since you don't seem to be waiting for asynchronous operations and this is not a GUI then neither of this applies to you.

The client calling your service might employ await/async, but that's a different problem.

What you could look into is Task (the parallel task library). But only if your tests truly can run in parallel and are substantial enough to be worth it! For tiny, fast & simple tests running them in parallel will likely hurt performance, not improve.

Finally, since this runs on a server, you need to take into account concurrent activities: is the server only servicing this request? Unless that's true you shouldn't use threads at all, keep things single-threaded and clean. Since all CPU-threads would be tied up in servicing other concurrent requests, running multiple Tasks or a ParallelLoop will only hurt performance, and not just for this request but for every other request that runs at the same time. That's because there would be no "free" cores to take your threads yet you do request them. There's no extra CPU capacity to tap into. You just end up doing context-switching (and paying the penalty for that) without getting any benefit.

As always: test, test, test.

Task class on MSDN: http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx

于 2013-10-07T04:24:46.680 回答