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 });
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!
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.
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 .
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:
MaximumConcurrencyLevel
, GetScheduledTasks
and TryExecuteTaskInline
.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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With