45

下面的代码将启动一个新线程来完成这项工作。有什么办法可以控制该线程的优先级吗?

Task.Factory.StartNew(() => {
    // everything here will be executed in a new thread.
    // I want to set the priority of this thread to BelowNormal
});
4

4 回答 4

60

正如其他人所提到的,您需要指定一个自定义调度程序来处理您的任务。不幸的是,没有合适的内置调度程序。

您可以选择 Glenn 链接到的 ParallelExtensionsExtras,但如果您想要一些可以直接粘贴到代码中的简单内容,请尝试以下操作。像这样使用:

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

编码:

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
    }
}

笔记:

  • 工作线程都是后台线程,所以不应该使用这个调度器来调度重要的任务;只有在进程关闭时可以丢弃的那些
  • 改编自Bnaya Eshet 的实现
  • 我不完全理解每一个覆盖;只是选择 Bnaya 的MaximumConcurrencyLevel,GetScheduledTasksTryExecuteTaskInline.
于 2012-01-29T20:56:47.527 回答
20

任务的线程优先级可以在执行任务的实际方法中设置。但是不要忘记在完成后恢复优先级以避免出现问题。

所以首先启动任务:

new TaskFactory().StartNew(StartTaskMethod);

然后设置线程优先级:

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;
    }
}

更改优先级时,请记住这一点:为什么*不*更改 ThreadPool(或任务)线程的优先级?

于 2012-01-09T16:22:12.653 回答
11

当您决定是否使用线程池时,这是“不做”之一;-)

更多细节在这里:http: //msdn.microsoft.com/en-us/library/0ka9477y.aspx

所以答案是“不,你不能为 Theads Pool 中创建的线程指定特定的优先级”

至于一般线程,我敢打赌你已经知道Thread.Priority属性

于 2010-10-01T04:52:26.047 回答
8

要设置优先级Task,请查看 Microsoft 专家Stephen Toub此 MSDN 博客文章中描述的自定义任务调度程序。有关更多详细信息,请不要错过他在第一句话中提到的前两篇文章的链接。

对于您的问题,听起来您可能想查看QueuedTaskScheduler.

于 2010-11-16T05:47:32.447 回答