如何以低优先级启动进程?C#

41

我想执行一个命令行工具来处理数据。它不需要阻塞。 我希望它是低优先级的。因此我编写了以下代码:

 Process app = new Process();
 app.StartInfo.FileName = @"bin\convert.exe";
 app.StartInfo.Arguments = TheArgs;
 app.PriorityClass = ProcessPriorityClass.BelowNormal;
 app.Start();

然而,我得到了一个“System.InvalidOperationException”错误,其中消息为“没有进程与此对象关联”。为什么?我该如何以低优先级正确启动此应用程序?

如果不加 app.PriorityClass = ProcessPriorityClass.BelowNormal; 这行代码,应用程序可以正常运行。

3个回答

53

在启动进程后,尝试设置PriorityClass。任务管理器采取这种方式,允许您为已经运行的进程设置优先级。


2
原来这是唯一的方法。 - user34537
正如Alois Kraus所指出的那样,这会导致竞态条件。微软设计时采用这种方式并不意味着它不是一个非常糟糕的想法。 - Paul Childs
无论是否存在竞态条件,我在这里看不到问题。该进程将短暂地在父进程的优先级中运行。 - Robert Harvey
2
这实际上是一个大问题。有时候这个时间足够长,以至于进程可以完成。因此,当它尝试设置已完成进程的优先级时,我最终会遇到间歇性运行时崩溃。这是一个严重的设计缺陷。 - Paul Childs

16
你可以通过一些小技巧创建一个低优先级的进程。你降低父进程的优先级,创建新进程,然后恢复回原来的进程优先级:
var parent   = Process.GetCurrentProcess();
var original = parent.PriorityClass;

parent.PriorityClass = ProcessPriorityClass.Idle;
var child            = Process.Start("cmd.exe");
parent.PriorityClass = original;

child 在开始时将具有 Idle 进程优先级。


2
这绝对是最佳解决方案,没有竞争。其他解决方案需要等待进程运行,如果您启动脚本并启动其他子进程,则可能会出现问题,因为这些子进程将以初始优先级而不是稍后设置的优先级运行。 - Alois Kraus
我真的不喜欢这个,但我更不喜欢调试间歇性错误。结果证明这实际上是唯一的方法。 - Paul Childs

7
如果您准备使用P/Invoke来调用CreateProcess,您可以在标志中传递CREATE_SUSPENDED。然后,在恢复进程之前,您可以调整进程优先级。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接