降低Task.Factory.StartNew线程的优先级

Moo*_*oon 35 .net c# multithreading .net-4.0 taskfactory

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

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

Rom*_*kov 54

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

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

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

代码:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 工作线程都是后台线程,因此不应使用此调度程序调度重要任务; 只有在进程关闭时才能丢弃的那些
  • 改编自Bnaya Eshet的实施
  • 我不完全理解每一个覆盖; 刚刚和Bnaya一起选择MaximumConcurrencyLevel,GetScheduledTasksTryExecuteTaskInline.

  • 看来现在这个地方在GitHub上有一个(未经认可的)地方,许可证已经改变(可能不合法),还有一些用于处理终结/处置的补充,尽管可能不是AppDomain本身关闭(IRegisteredObject). (5认同)
  • 如果您只是想利用 TaskParallelLibrary 的易用性并设置优先级,那真是太冗长了……虽然没有冒犯。谢谢你的回答。 (2认同)

net*_*rog 18

可以在执行任务的实际方法内设置任务的线程优先级.但是,一旦完成以避免问题,不要忘记恢复优先级.

所以首先启动任务:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这种方法对我来说似乎很危险.是不是在其中一个ThreadPool线程上设置优先级?您不知道接下来将使用该线程的位置. (6认同)
  • (上面的注释现在已经过时了,因为代码已经更新为使用try..finally.但是可以进一步改进以捕获初始线程优先级,而不是将值设置回Normal.) (4认同)
  • @net_prog,我想你不明白布兰农的观点。线程池中的线程被重新使用。下次您要重新使用线程时,您必须确保适当的优先级。默认行为是让线程处于正常优先级。如果您使用使用线程池的第三方库,如果优先级不符合预期,您可能会遇到麻烦。 (2认同)

zer*_*kms 6

当你决定是否使用线程池时,这是"不要做"之一;-)

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

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

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

  • 是的我知道Thread.Priority.但我只是想知道是否可以使用Task Factory而不是使用Thread的对象. (4认同)

Gle*_*den 5

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

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