如何控制 Task.Factory.StartNew 线程的优先级?

共 2870字,需浏览 6分钟

 ·

2021-12-10 16:50

咨询区

  • 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 方法体中的线程优先级,两位大佬提供的方法都特别好,学习了。

浏览 135
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报