40

I want to execute a command line tool to process data. It does not need to be blocking. I want it to be low priority. So I wrote the below

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

However, I get a System.InvalidOperationException with the message "No process is associated with this object." Why? How do I properly launch this app in low priority?

Without the line app.PriorityClass = ProcessPriorityClass.BelowNormal; the app runs fine.

mafu
  • 31,798
  • 42
  • 154
  • 247

3 Answers3

52

Try setting the PriorityClass AFTER you start the process. Task Manager works this way, allowing you to set priority on a process that is already running.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • 2
    Turns out this is the only way. –  Jun 23 '10 at 15:48
  • As pointed out by Alois Kraus this gives a race condition. The fact that this is the way it is designed to be done by Microsoft does not make it any less a very BAD idea. – Paul Childs Sep 15 '21 at 02:46
  • Race condition or not, I don't see the problem here. The process would *momentarily* be running in the parent process's priority. – Robert Harvey Sep 15 '21 at 03:02
  • 2
    It is actually a big problem. I get occasions when this moment is long enough for the process to complete. I thus end up with an intermittent run time crash when it tries to set the priority of a finished process. This is a serious design flaw. – Paul Childs Sep 24 '21 at 01:11
16

You can create a process with lower priority by doing a little hack. You lower the parent process priority, create the new process and then revert back to the original process priority:

var parent   = Process.GetCurrentProcess();
var original = parent.PriorityClass;

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

child will have the Idle process priority right at the start.

Pablo Montilla
  • 2,941
  • 1
  • 31
  • 35
  • 2
    That is by far the best solution with no races. The other solutions need to wait until the process is running which can be an issue if you start e.g. a script which starts other child processes which will then run with the initial priority and not the one you will set later. – Alois Kraus Nov 12 '19 at 12:55
  • I really don't like this, but I like debugging intermittent errors less. Turns out this is actually the only way. – Paul Childs Sep 24 '21 at 01:13
7

If you're prepared to P/Invoke to CreateProcess, you can pass CREATE_SUSPENDED in the flags. Then you can tweak the process priority before resuming the process.

Roger Lipscombe
  • 89,048
  • 55
  • 235
  • 380