2

我有一个队列,里面有 144 个项目。每个队列元素都是一个请求。我试图通过尝试并行运行代码来提高处理性能。我调用 performaction(request) 方法。它实例化一个对象并将请求传递给它并执行一个操作。我可以并行运行此操作,因为这些请求是独立的,并且请求的操作结果也彼此独立。首先我试过

foreach(var request in queue.Values)
    Parallel.Invoke(() =>PerformAction(request);

然后我尝试了相同的 foreach。

var task = new Task(() => PerformAction(request));
task.Start();

在我拥有的 foreach 之外

Task.WaitAll();

当运行程序时,parallel.invoke 需要将近 3 秒才能完成,而 Task 需要将近 0.005 秒才能完成。

我有以下问题:

  1. 为什么并行调用比任务花费更多时间?似乎并行调用没有像我想要的那样以并行模式运行。
  2. 当我使用任务时,对于每个请求我都创建一个新任务,如果我有 1000 个请求的请求,我最终会创建 1000 个线程还是 CPU 会根据需要处理创建线程?
  3. Task.WaitAll() 在程序终止之前它会等待所有任务完成吗?
4

1 回答 1

9

您的代码中的问题是Task.WaitAll()它不能按您的预期工作。您已保存并开始了一项任务:

var task = new Task(() => PerformAction(request));
task.Start();

但是您没有保留对要传递给的每个任务的引用WaitAll。您的目的是将所有任务保存在一个数组中,然后将该数组传递给WaitAll. 因此,您的程序使用任务“快速”执行,因为它没有等待完成。

你的问题:

  1. 请参阅上文了解为什么Parallel.Invoke需要更多时间 - 因为它实际运行。但是,您也没有正确使用它。Parallel.Invoke 采用一系列动作 ( Actions[]) 并尝试并行运行它们。您每次都用一个动作多次调用它。我什至不确定你的代码是如何编译的。我相信你想要的是:

    Parallel.ForEach(queue.Values, request => PerformAction(request))
    
  2. 您正在为每个请求创建一个新任务,但这不会与线程一一对应。默认情况下,任务使用线程池

  3. Task.WaitAll(tasks)确实等待所有tasks完成。但如果你什么都不通过,它就不会。同样,这不应该像你拥有的那样编译。

于 2012-04-16T04:15:35.287 回答