我们正在开发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());
我们在这里缺少什么?
谢谢, 尼尔。
答案 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个内核。如果你没有那么多,那就无法做到......
在正常情况下,因为许多任务将被并行调度为最适合您的系统