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

发布于 2024-09-25 15:35:34 字数 233 浏览 5 评论 0 原文

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

碍人泪离人颜 2024-10-02 15:35:34

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

您可以使用 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 对 MaximumConcurrencyLevelGetScheduledTasksTryExecuteTaskInline 的选择即可。

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 = 
quot;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.
醉南桥 2024-10-02 15:35:34

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

所以首先启动任务:

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(或任务)线程的优先级?

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?

_畞蕅 2024-10-02 15:35:34

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

更多详细信息请参见:http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

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

”我打赌您已经了解Thread.Priority< /a> 属性

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

吃颗糖壮壮胆 2024-10-02 15:35:34

要使用 Task 设置优先级,请查看 Microsoft 专家 Stephen Toub这篇 MSDN 博客文章。有关更多详细信息,请不要错过他在第一句话中提到的前两篇文章的链接。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文