3

Background
Historically, I've not had to write too much thread related code. I am familiar with the process and I can use System.Threading to do what I need to do when the need arises. However, the bulk of my experience has been stuck in .Net 2.0 world (ugh!) and I need a bit of help executing a very simple task in the most recent version of .Net.

I need to write a simple, parallel job but I would prefer it to execute as a low-priority task that doesn't bring my PC to a sluggish halt.

Below is a simple parallel example that demonstrates the type of work that I'm trying to accomplish. In this example, I take a random number and I store it if the new value is larger than the last, largest random number that has been discovered.

Please understand, the point of this example is to strictly show that I have a calculation that I wish to repeatedly execute, compare and store. I understand the need for variable locking and I also know that this code isn't perfect. However, it is an extremely simple example of the nature of what I need to accomplish. If you run this code, your CPU will come to a grinding halt.

int i = 0;
ThreadSafeRNG r = new ThreadSafeRNG();
ParallelOptions.MaxDegreeOfParallelism = 4; //Assume I have 8 cores.
Parallel.For(0, Int32.MaxValue, (j, loopState) => 
{
    int k = r.Next();
    if (k > i) k = i;
}

How can I do this work, in parallel, and have it execute as a low-priority CPU job. The above mechanism has provided tremendous performance improvements, over a standard for-loop. However, the cost has been that I can't use my computer, even after setting the MaxDegreeOfParallelism option.

What can I do?

RLH
  • 15,230
  • 22
  • 98
  • 182
  • Not a duplicate, but related question [here](http://stackoverflow.com/questions/13089003/set-priority-for-parallel-for-loop) – Sven Grosen Dec 17 '13 at 17:21
  • Thanks @ledbutter. I think that was one of the first posts I found that pointed to using the `ParallelOptions` object. However, what I've found is that I need to set the value to something REALLY low, to see a difference. Even then, my computer is noticeably slower, but it does become usable. This is kind of a non-option. – RLH Dec 17 '13 at 17:39
  • 1
    By the way, the non-static methods on `Random` are not thread-safe – harold Dec 17 '13 at 17:58
  • Stephen Toub has [a blog post describing a thread-safe way to use the `Random` class](http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx). – Richard Deeming Dec 17 '13 at 18:33
  • Sigh... thank you guys for commenting, but this post isn't about the Random class of .Net. I am aware that it isn't thread safe. I could have just as easily made this a call to a method called `DoSimpleThreadSafeWork()` and that would have sufficed for the purpose of this question. – RLH Dec 17 '13 at 18:40
  • This will probably not count as "simplest", but a custom thread pool would do. It doesn't need to be fancy. – Jon Dec 17 '13 at 22:31
  • Some other relevant info http://stackoverflow.com/questions/5589376/why-not-change-the-priority-of-a-threadpool-or-task-thread. – oleksii Dec 17 '13 at 22:36

2 Answers2

2

Because Parallel.For uses ThreadPool threads you can not set the priority of the thread to be low. However you can change the priority of the entire application

Process currentProcess = Process.GetCurrentProcess();
ProcessPriorityClass oldPriority = currentProcess.PriorityClass;

try
{
    currentProcess.PriorityClass = ProcessPriorityClass.BelowNormal;

    int i = 0;
    ThreadSafeRNG r = new ThreadSafeRNG();
    ParallelOptions.MaxDegreeOfParallelism = 4; //Assume I have 8 cores.
    Parallel.For(0, Int32.MaxValue, (j, loopState) => 
    {
        int k = r.Next();
        if (k > i) k = i;
    }
}
finally
{
    //Bring the priority back up to the original level.
    currentProcess.PriorityClass = oldPriority;
}

If you really don't want your whole application's priority to be lowered combine this trick with some form of IPC like WCF and have your slow long running operation running in a 2nd process that you start up and kill as needed.

Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
0

Using the Parallel.For method, you cannot set thread priority since they are ThreadPool threads.

Your best bet is to set ParallelOptions.MaxDegreeOfParallelism to ProcessorCount - 1, this way you have a free core to do other things (such as handle the GUI).

Erik
  • 12,730
  • 5
  • 36
  • 42