2010-10-01 5 views
28

un code comme ci-dessous va démarrer un nouveau thread pour faire le travail. Est-il possible de contrôler la priorité de ce thread?priorité inférieure de 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 
}); 

Répondre

6

C'est l'un des « ne pas faire » lorsque vous décidez d'utiliser ou non pool de threads ou non ;-)

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

Donc, la réponse est « Non, ne peut pas spécifier une priorité particulière pour le fil créé dans Theads Pool »

au général taraudages Je parie que vous connaissez déjà Thread.Priority propriété

+3

Oui, je connais Thread.Priority. Mais je voulais juste savoir si c'était possible avec Task Factory au lieu d'utiliser des objets de Thread. – Moon

+0

Au premier lien c'est une description qui dit que ce n'est pas possible avec Task Factory.De toute façon je n'ai jamais besoin de changer la priorité pour les threads de la piscine et je ne suis pas sûr à 100% que c'est la vérité. – zerkms

5

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

Pour votre problème, il semble que vous souhaitiez regarder le QueuedTaskScheduler.

15

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.

Alors d'abord démarrer la tâche:

new TaskFactory().StartNew(StartTaskMethod);

Réglez ensuite la priorité de fil:

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

Lors du changement de priorité, garder à l'esprit ceci: Why *not* change the priority of a ThreadPool (or Task) thread?

+6

Cette approche me semble dangereuse. Ce paramètre n'est-il pas prioritaire sur l'un des threads ThreadPool? Vous ne savez pas où ce fil sera utilisé ensuite. – Brannon

+0

@Brannon, changer la priorité via le planificateur de tâches aura un effet similaire, je suppose. En général, vous ne modifiez pas du tout la priorité, mais si vous avez besoin de le faire, il n'y a pas de différence. –

+1

@ net_prog, je pense que vous ne comprenez pas le point de Brannon. Un thread d'un pool de threads est fait pour être réutilisé. La prochaine fois que vous voudrez réutiliser un thread, vous devrez assurer la priorité appropriée. Le comportement par défaut est d'avoir un thread en priorité normale. Si vous utilisez une librairie tierce qui utilise le pool de threads, vous pouvez tomber dans des problèmes si la priorité n'est pas celle attendue. –

41

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

Vous pouvez opter pour ParallelExtensionsExtras auquel Glenn est lié, mais si vous voulez que quelque chose de simple puisse être simplement 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 
    } 
} 

Notes:

  • les threads de travail sont toutes les discussions de fond, ne doivent pas être des tâches planifiées si importantes en utilisant ce planificateur; seulement ceux qui peuvent être mis au rebut si le processus s'arrête
  • adapté de an implementation by Bnaya Eshet
  • Je ne comprends pas complètement chaque dérogation; juste aller avec les choix de Bnaya pour MaximumConcurrencyLevel, GetScheduledTasks et TryExecuteTaskInline.
+5

a maintenant une place (non crédité) sur GitHub, avec la licence changée (probablement pas légale) et quelques ajouts pour faire face à la finalisation/disposition, bien que peut-être pas l'AppDomain lui-même descendant (IRegisteredObject). –

+1

Comment merveilleusement verbeux si vous voulez juste utiliser la facilité de la TaskParallelLibrary ET définir une priorité ... Pas d'offense cependant. Merci d'avoir répondu. –

Questions connexes