Delphi 12(已打补丁)TParallel.For循环结束后CPU占用过高求助
Delphi 12 TParallel.For 执行后CPU高占用问题解决办法
问题重现代码
procedure TForm1.Button2Click(Sender: TObject); var lF: TParallel; begin lF := TParallel.Create; try lF.&For(1, 100000, procedure(I: Integer) var x: Integer; lList: TStringList; begin lList := TStringList.Create; try lList.Add(i.ToString); finally lList.Free; end; end ); finally FreeAndNIL(lF); end; end;
问题现象
- Delphi 11.3中,仅TParallel.For执行期间占用CPU,循环结束后CPU占用率恢复至0
- Delphi 12(已打补丁)中,循环执行结束后CPU仍保持高占用状态
- 调整
TThreadPool.Default.SetMaxWorkerThreads参数后问题未解决
可行解决办法
1. 改用TParallel静态方法(推荐)
TParallel的设计初衷是使用其静态方法而非手动实例化对象,手动创建TParallel实例可能导致线程池资源无法正确回收。修改代码如下:
procedure TForm1.Button2Click(Sender: TObject); begin TParallel.&For(1, 100000, procedure(I: Integer) var lList: TStringList; begin lList := TStringList.Create; try lList.Add(I.ToString); finally lList.Free; end; end); end;
2. 配置线程池空闲超时
如果必须保留实例化方式,可在循环结束后显式设置线程池的空闲线程超时,让闲置线程自动销毁:
procedure TForm1.Button2Click(Sender: TObject); var lF: TParallel; begin lF := TParallel.Create; try lF.&For(1, 100000, procedure(I: Integer) var lList: TStringList; begin lList := TStringList.Create; try lList.Add(I.ToString); finally lList.Free; end; end); // 配置线程池参数,让闲置线程自动退出 TThreadPool.Default.SetMinWorkerThreads(0); TThreadPool.Default.SetMaxWorkerThreads(Environment.Process.Affinity.Count); TThreadPool.Default.IdleThreadTimeout := 1000; // 闲置1秒后销毁线程 finally FreeAndNIL(lF); end; end;
3. 手动终止线程池(极端场景)
若上述方法无效,可在循环结束后手动终止线程池(注意:此操作会销毁所有线程池线程,可能影响其他依赖线程池的代码):
finally FreeAndNIL(lF); TThreadPool.Default.Terminate; end;
问题原因分析
Delphi 12对TParallel和TThreadPool的内部实现做了调整,手动实例化TParallel可能打破了线程池的资源回收逻辑,导致线程池中的工作线程在任务结束后仍保持活跃状态,持续占用CPU资源。而Delphi 11.3的线程池回收机制更激进,闲置线程会快速退出。
内容的提问来源于stack exchange,提问作者Toni Grabmayr
相关产品推荐
相关产品推荐

