如何控制 Task.Factory.StartNew 线程的优先级?
咨询区
John Saunders
我的项目有一个需求,需要控制 Task 线程的优先级,代码如下:
Task.Factory.StartNew(() => {
// everything here will be executed in a new thread.
// I want to set the priority of this thread to BelowNormal
});
回答区
Roman Starkov:
要想控制 Task 的优先级,底层框架没有内建这种机制,所以除了自定义 scheduler 我觉得毫无办法,可以参考我的实现。
首先要自定义的 PriorityScheduler ,因为 Task 内部有一个中枢神经抽象类 TaskScheduler
,要想实现自定义的只需要继承一下就可以了。
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 _tasks = new BlockingCollection();
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 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
}
}
接下来就可以在 StartNew 方法中指定自定义的 Scheduler。
Task.Factory.StartNew(() => {
// everything here will be executed in a thread whose priority is BelowNormal
}, null, TaskCreationOptions.None, PriorityScheduler.BelowNormal);
net_prog:
要想设置 thread 优先级,可以在Task运行的方法体中设置当前线程的优先级,然后在方法体执行结束前再重新设置优先级,参考如下代码:
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;
}
}
最后就是将方法丢到 StartNew
中。
new TaskFactory().StartNew(StartTaskMethod);
点评区
修改 Task 方法体中的线程优先级,两位大佬提供的方法都特别好,学习了。
评论