понижение приоритета потока Task.Factory.StartNew - PullRequest
35 голосов
/ 01 октября 2010

код, подобный приведенному ниже, запустит новый поток для выполнения работы.Есть ли способ, которым я могу контролировать приоритет этого потока?

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

Ответы [ 4 ]

52 голосов
/ 30 января 2012

Как уже упоминалось, вам нужно указать собственный планировщик для выполнения вашей задачи.К сожалению, нет подходящего встроенного планировщика.

Вы могли бы пойти на 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 = 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
    }
}

Примечания:

  • все рабочие потоки - это фоновые потоки, поэтому важных задач не должно бытьпо расписанию с использованием этого планировщика;только те, которые могут быть отброшены, если процесс выключается
  • , адаптированный из реализации Бной Эшет
  • Я не до конца понимаю все переопределения;просто с выбором Бная ​​для MaximumConcurrencyLevel, GetScheduledTasks и TryExecuteTaskInline.
17 голосов
/ 09 января 2012

Приоритет потока для Задач может быть установлен внутри фактического метода, который выполняет Задачу. Но не забудьте восстановить приоритет, как только вы закончите, чтобы избежать проблем.

Итак, сначала запустите задачу:

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 (или Задачи)?

6 голосов
/ 01 октября 2010

Это одно из "не делать", когда вы решаете, использовать ли пул потоков или нет; -)

Подробнее здесь: http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

Таким образом, ответ "Нет", вы не можете указать конкретный приоритет для потока, созданного в Theads Pool "

Что касается общих потоков, я уверен, вы уже знаете о Thread.Priority свойство

5 голосов
/ 16 ноября 2010

Для установки приоритета с помощью Task ознакомьтесь с пользовательскими планировщиками задач, описанными экспертом Microsoft Стивеном Таубом в этого сообщения в блоге MSDN .Для получения более подробной информации, не пропустите ссылки на предыдущие два поста, которые он упоминает в первом предложении.

Для вашей проблемы, похоже, вы захотите взглянуть на QueuedTaskScheduler.

...