web-dev-qa-db-fra.com

abaisser la priorité du thread Task.Factory.StartNew

un code comme ci-dessous lancera un nouveau thread pour faire le travail. Existe-t-il un moyen de contrôler la priorité de ce thread?

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

Il s'agit de "ne pas faire" lorsque vous décidez d'utiliser ou non le pool de threads ;-)

Plus de détails ici: http://msdn.Microsoft.com/en-us/library/0ka9477y.aspx

La réponse est donc "Non, vous ne pouvez pas spécifier de priorité particulière pour le thread créé dans le pool de threads"

En ce qui concerne les discussions générales, je parie que vous connaissez déjà la propriété Thread.Priority

6
zerkms

Comme d'autres l'ont mentionné, vous devez spécifier un planificateur personnalisé pour accompagner votre tâche. Malheureusement, il n'y a pas de planificateur intégré approprié.

Vous pouvez opter pour les ParallelExtensionsExtras auxquels Glenn a lié, mais si vous voulez quelque chose de simple qui peut être collé directement dans votre code, essayez ce qui suit. Utilisez comme ceci:

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

Le 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 = 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
    }
}

Remarques:

  • les threads de travail sont tous des threads d'arrière-plan, donc les tâches importantes ne doivent pas être planifiées à l'aide de ce planificateur; seulement ceux qui peuvent être jetés si le processus s'arrête
  • adapté de ne implémentation par Bnaya Eshet
  • Je ne comprends pas parfaitement chaque dérogation; juste aller avec les choix de Bnaya pour MaximumConcurrencyLevel, GetScheduledTasks et TryExecuteTaskInline.
56
Roman Starkov

La priorité de thread pour les tâches peut être définie dans la méthode réelle qui exécute la tâche. Mais n'oubliez pas de restaurer la priorité une fois que vous avez terminé pour éviter les problèmes.

Commencez donc d'abord la tâche:

new TaskFactory().StartNew(StartTaskMethod);

Définissez ensuite la priorité du thread:

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

Lorsque vous changez la priorité, gardez à l'esprit ceci: Pourquoi * pas * changer la priorité d'un thread ThreadPool (ou Task)?

18
net_prog

Pour définir la priorité avec Task, consultez les planificateurs de tâches personnalisés décrits par l'expert Microsoft Stephen Toub in this blog MSDN = . Pour plus de détails, ne manquez pas les liens vers les deux postes précédents qu'il mentionne dans la première phrase.

Pour votre problème, il semble que vous souhaitiez peut-être regarder le QueuedTaskScheduler.

6
Glenn Slayden