IIS托管.NET OpenRia服务多线程计算逐次变慢重启恢复问题咨询
问题根因
你的性能下降问题核心来自三个叠加因素:
- 原生DLL的线程资源泄漏:你调用的求解线性系统的原生DLL大概率存在线程本地存储(TLS)、句柄泄漏问题,线程池复用这些被污染的线程时,要么执行效率下降,要么被系统标记为异常状态,线程池会主动降低这类线程的调度优先级。
- IIS线程池的节流机制:默认ASP.NET线程池的线程注入速度有限,且你当前代码用
Task.WaitAll阻塞了当前请求的IIS工作线程,每次请求都会额外占用一个线程池线程。多次请求后可用线程池线程数持续下降,达不到你预期的60并发度。 - 你的代码中
ParallelOptions使用完全无效:默认ParallelOptions.MaxDegreeOfParallelism值为-1,你直接用它初始化Task数组长度,实际第一次运行时是线程池动态注入到60个线程,后续线程池资源不足时就无法达到该并发度。
修复方案
- 优先修复原生DLL资源问题:确认每次调用
LoadLibrary加载DLL后,在计算结束时执行对应的FreeLibrary释放资源;排查原生DLL的线程相关资源释放逻辑,避免TLS、内存泄漏。 - 避免线程池线程被污染:如果原生DLL泄漏问题无法快速修复,不要用线程池线程承载计算任务,改为直接创建独立线程执行,计算结束后线程自动销毁,不会被复用:
// 固定并发数为60,不要依赖默认参数 const int MaxConcurrency = 60; Thread[] threads = new Thread[MaxConcurrency]; for (int i = 0; i < MaxConcurrency; i++) { threads[i] = new Thread(() => StartAnalysis(events)) { IsBackground = true, Priority = ThreadPriority.Normal }; threads[i].Start(); } foreach (var thread in threads) { thread.Join(); }
- 调整IIS线程池配置,在web.config中添加以下配置,避免线程注入节流:
<configuration> <system.web> <!-- 最小工作线程和IO线程数设置为高于你的并发数 --> <processModel minWorkerThreads="100" minIoThreads="100" /> <httpRuntime minFreeThreads="90" minLocalRequestFreeThreads="80" /> </system.web> </configuration>
- 优化异步逻辑:如果要继续用Task实现,将阻塞的
Task.WaitAll改为异步等待await Task.WhenAll,释放当前IIS工作线程回线程池,减少不必要的线程占用。 - 可选优化:将
ConcurrentStack改为ConcurrentQueue,避免任务顺序倒置带来的调度损耗,不过该调整对核心性能下降问题无影响。
内容的提问来源于stack exchange,提问作者Alessandro
相关产品推荐
相关产品推荐

