WebAPI中的线程(任务)限制(或一般而言)

时间:2017-05-20 21:12:22

标签: c# multithreading asp.net-web-api limit

我们正在开发WebAPI,它具有大约200个项目的解密逻辑(可以更多)。每次解密大约需要20ms。 我们已尝试将任务并行,以便我们尽快完成任务,但似乎我们正在获得某种限制,因为线程通过等待旧线程得到重用完成(并且只使用了很少) - 整体动作大约需要1-2秒才能完成...

我们基本上想要实现的是获取x个线程数量同时启动并在那些~20毫秒之后完成。

我们试过这个: Await multiple async Task while setting max running task at a time

但似乎这只描述了设置限制,而我们想要发布它......

这是一个片段:

                    var tasks = new List<Task>();
                    foreach (var element in Elements)
                    {
                        var task = new Task(() =>
                        {
                          element.Value = Cipher.Decrypt((string)element.Value);
                        }
                        });
                        task.Start();
                        tasks.Add(task);
                    }
                    Task.WaitAll(tasks.ToArray());

我们在这里缺少什么?

谢谢, 尼尔。

2 个答案:

答案 0 :(得分:1)

我不能推荐ASP.NET上的并行性。它肯定会影响您的服务的可扩展性,特别是如果它是面向公众的。我曾经想过“哦,我足够聪明地做到这一点”并且在ASP.NET应用程序中增加了并行性,但只需要在一周后将其撕掉。

但是,如果您真的想要到......

  

似乎我们正在获得某种限制

是您机器上物理核心的限制吗?

  

我们尝试过:在一次设置最大运行任务时等待多个异步任务

该解决方案专门用于异步并发代码(例如,I / O绑定)。你想要的是并行(线程)并发代码(例如,CPU绑定)。完全不同的用例和解决方案。

  

我们在这里缺少什么?

您当前的代码在线程池中投入了大量的同时任务,它们将尝试尽可能地处理它们。您可以通过使用更高级别的抽象来提高效率,例如Parallel

Parallel.ForEach(Elements, element =>
{
  element.Value = Cipher.Decrypt((string)element.Value);
});

Parallel在分割和(重新)使用线程方面更加智能(即,不超过核心数)。所以你应该看到一些加速。

然而,我希望它只是一个小的加速。您可能受到物理核心数量的限制。

答案 1 :(得分:0)

假设没有超线程:

如果1个项目需要20毫秒,那么您可以将其视为需要1个核心20毫秒。如果您想在20毫秒内完成200个项目,那么您需要200个内核。如果你没有那么多,那就无法做到......

在正常情况下,因为许多任务将被并行调度为最适合您的系统