Подтвердить что ты не робот

Снижая приоритет Task.Factory.StartNew thread

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

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

Ответ 1

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

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

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

Как и общие потоки, я уверен, вы уже знаете о Thread.Priority property

Ответ 2

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

Вы можете пойти на 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
    }
}

Примечания:

  • рабочие потоки - это фоновые потоки, поэтому важные задачи не должны планироваться с помощью этого планировщика; только те, которые могут быть отброшены, если процесс завершает работу
  • адаптирован из реализация Bnaya Eshet
  • Я не полностью понимаю каждое переопределение; просто перейдя с вариантами Bnaya для MaximumConcurrencyLevel, GetScheduledTasks и TryExecuteTaskInline.

Ответ 3

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

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

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 (или Task)?

Ответ 4

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

Для вашей проблемы кажется, что вы можете посмотреть на QueuedTaskScheduler.