Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lowering priority of Task.Factory.StartNew thread

a code like below will start a new thread to do the job. Is there any way I can control the priority of that thread?

Task.Factory.StartNew(() => {     // everything here will be executed in a new thread.     // I want to set the priority of this thread to BelowNormal }); 
like image 440
Moon Avatar asked Oct 01 '10 04:10

Moon


People also ask

What is the difference between task run () and Taskfactory StartNew () methods?

Run(action) internally uses the default TaskScheduler , which means it always offloads a task to the thread pool. StartNew(action) , on the other hand, uses the scheduler of the current thread which may not use thread pool at all!

What is task factory StartNew in C#?

StartNew(Action<Object>, Object, CancellationToken, TaskCreationOptions, TaskScheduler) Creates and starts a task for the specified action delegate, state, cancellation token, creation options and task scheduler.

Can we set different priority of a thread in C#?

A programmer can explicitly assign priority to a thread. The by default priority of a thread is Normal. Operating system does not assign the priority of threads. If a thread has reached a final state, such as Aborted, then this will give ThreadStateException .


2 Answers

As others have mentioned, you need to specify a custom scheduler to go with your task. Unfortunately there isn't a suitable built-in scheduler.

You could go for the ParallelExtensionsExtras that Glenn linked to, but if you want something simple that can just be pasted right into your code, try the following. Use like this:

Task.Factory.StartNew(() => {     // everything here will be executed in a thread whose priority is BelowNormal }, null, TaskCreationOptions.None, PriorityScheduler.BelowNormal); 

The code:

public class PriorityScheduler : TaskScheduler {     public static PriorityScheduler AboveNormal = new PriorityScheduler(ThreadPriority.AboveNormal);     public static PriorityScheduler BelowNormal = new PriorityScheduler(ThreadPriority.BelowNormal);     public static PriorityScheduler Lowest = new PriorityScheduler(ThreadPriority.Lowest);      private BlockingCollection<Task> _tasks = new BlockingCollection<Task>();     private Thread[] _threads;     private ThreadPriority _priority;     private readonly int _maximumConcurrencyLevel = Math.Max(1, Environment.ProcessorCount);      public PriorityScheduler(ThreadPriority priority)     {         _priority = priority;     }      public override int MaximumConcurrencyLevel     {         get { return _maximumConcurrencyLevel; }     }      protected override IEnumerable<Task> GetScheduledTasks()     {         return _tasks;     }      protected override void QueueTask(Task task)     {         _tasks.Add(task);          if (_threads == null)         {             _threads = new Thread[_maximumConcurrencyLevel];             for (int i = 0; i < _threads.Length; i++)             {                 int local = i;                 _threads[i] = new Thread(() =>                 {                     foreach (Task t in _tasks.GetConsumingEnumerable())                         base.TryExecuteTask(t);                 });                 _threads[i].Name = $"PriorityScheduler: {i}";                 _threads[i].Priority = _priority;                 _threads[i].IsBackground = true;                 _threads[i].Start();             }         }     }      protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)     {         return false; // we might not want to execute task that should schedule as high or low priority inline     } } 

Notes:

  • the worker threads are all background threads, so important tasks should not be scheduled using this scheduler; only those which can be discarded if the process shuts down
  • adapted from an implementation by Bnaya Eshet
  • I don't fully understand every override; just going with Bnaya's choices for MaximumConcurrencyLevel, GetScheduledTasks and TryExecuteTaskInline.
like image 89
Roman Starkov Avatar answered Oct 23 '22 16:10

Roman Starkov


Thread priority for Tasks can be set inside the actual method that executes the Task. But don't forget to restore the priority once you are done to avoid problems.

So first start the Task:

new TaskFactory().StartNew(StartTaskMethod);

Then set the thread priority:

void StartTaskMethod() {     try     {         // Change the thread priority to the one required.         Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;          // Execute the task logic.         DoSomething();     }     finally     {         // Restore the thread default priority.         Thread.CurrentThread.Priority = ThreadPriority.Normal;     } } 

When changing the priority, keep in mind this: Why *not* change the priority of a ThreadPool (or Task) thread?

like image 23
net_prog Avatar answered Oct 23 '22 17:10

net_prog