You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForms非阻塞调用外部进程的正确实现及相关内存泄漏问题排查

问题根因

你当前的实现存在两个核心问题:

  1. Process类属于非托管资源包装类,你创建实例后没有主动释放,会导致调用方进程累积句柄泄漏和内存泄漏,长时间运行后触发服务器无响应。
  2. splwow64.exe是Windows系统用于兼容32位/64位打印任务的中间进程,当打印程序未正确释放打印上下文、且直接向网络打印服务器发送任务时,会累积打印元数据缓存,导致内存持续增长。

正确实现方案

1. 调用方进程资源无占用的启动写法

使用using块包裹Process实例,启动完成后自动释放所有关联资源,不需要等待被调用程序执行完成:

using (System.Diagnostics.Process LOProc = new System.Diagnostics.Process())
{
    LOProc.StartInfo.FileName = PSParmServicePGM;
    LOProc.StartInfo.Arguments = PSGUID;
    // 可选配置,避免继承调用方资源、不弹出多余窗口
    LOProc.StartInfo.UseShellExecute = true;
    LOProc.StartInfo.CreateNoWindow = true;
    LOProc.Start();
}
// 出using块后调用方已释放所有对子进程的引用,不会占用任何调用方资源

如果完全不需要关心子进程的运行状态,也可以使用更彻底的脱离进程树的启动方式,调用方完全不持有子进程句柄:

System.Diagnostics.Process.Start("cmd.exe", $"/c start \"\" \"{PSParmServicePGM}\" {PSGUID}");

2. 解决splwow64.exe内存增长问题

  • 优化打印程序逻辑:每次打印任务完成后,主动释放所有Crystal Reports COM对象、打印上下文资源,执行强制垃圾回收,从根源减少打印缓存残留。
  • 调用方增加定期清理逻辑:在业务低峰期(比如每天凌晨)清理无活跃任务的splwow64进程:
foreach (var proc in System.Diagnostics.Process.GetProcessesByName("splwow64"))
{
    try
    {
        if (proc.Responding)
        {
            proc.Kill();
            proc.WaitForExit(1000);
        }
        proc.Dispose();
    }
    catch { }
}

内容的提问来源于stack exchange,提问作者James Williams

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 21:15:03