在Asp.NET MVC应用程序中,我有一个项目,其中包含要跟踪的活动图。
项目没有单个根但有多个根。 每棵树都可能是复杂而深刻的,每个节点都依赖于日期和细粒度用户权限等其他节点。
每次在节点上进行操作时,我都需要处理所有项目图 因为即使不同的分支也相互依赖。
结构平面存储在SqlServer DB中。
为了创建树,我有一个递归函数,可以为每个节点创建一些数据(在当前用户的上下文中)。
例如,我有一个包含3000个节点的项目,只需一次调用即可创建整个图形,处理时间超过2秒。
public static List<Nodes> GetProject(...) {
var list = new List<Nodes>;
CreateTreeRecursive(...);
return list;
}
请记住,我有多个根。这让我可以独立地并行化每个分支的工作和处理。
如果我使用Task.Run或Parallel.ForEach并行执行,则创建整个图形的时间在15到50毫秒之间,快50倍。
public static List<Nodes> GetProject2(...) {
var list = new List<Nodes>;
Parallel.ForEach(...,
(root) => {
...
});
return list;
}
坏消息是你不应该在ASP.NET中创建线程。
在特定情况下,我没有多个并发用户,但拥有约200名用户 你无法确切地知道。
另一件事是项目的根源可能很多,最多100个,所以很多线程会 被创造。
这个解决方案很简单但不适用。
有没有办法以简单的方式做到这一点,或者我唯一的选择是将工作卸载给某些人 可以跨越多个线程并等待异步的外部服务?
如果是这种情况,我会很感激一些建议吗?
要清楚这是为项目上的任何用户交互而进行的操作。 我不能缓存结果,太不稳定了。我不能在某个地方入队,最终得到结果。
由于
答案 0 :(得分:1)
坏消息是你不应该在ASP.NET中创建线程。
事实并非如此,这种错误的假设阻碍了正确的解决方案。
您可以创建线程。您可能想到的风险是您可能耗尽线程池的容量。这一般不容易做到。
您的线程受CPU限制。这意味着您的服务器在池耗尽之前很久就会过载。池容量不是您的限制因素。
通过一些假设我们可以构成一个具体的场景:一个8核心服务器在8个线程(这里可以像这样运行)饱和。但是,如果少于100个线程,则不会将线程池视为重载。 (实际数量各不相同.100在各种情况下应该是安全的。)
此外,Parallel.ForEach
使用池线程。它不会创建有意义的线程数量。它也不会占用每个输入项的一个线程。
我在这里看不到任何担心。