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
});
This is one of "not to do" when you decide whether to use thread pool or not ;-)
More details here: http://msdn.microsoft.com/en-us/library/0ka9477y.aspx
So the answer is "No, you cannot specify particular priority for thread created in Theads Pool"
As of general threadings I bet you already know about Thread.Priority property
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 = string.Format("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
.
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?
For setting priority with Task
, check out the custom task schedulers described by Microsoft expert Stephen Toub in this MSDN blog post. For further detail, don't miss the links to the previous two posts that he mentions in the first sentence.
For your issue, it sounds like you might want to look at the QueuedTaskScheduler
.