2010-10-01 9 views
28

ein Code wie unten startet einen neuen Thread, um die Aufgabe zu erledigen. Gibt es eine Möglichkeit, die Priorität dieses Threads zu kontrollieren?Senken Priorität von 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 
}); 

Antwort

6

Dies ist einer der "nicht zu tun", wenn Sie entscheiden, ob Thread-Pool verwenden oder nicht ;-)

Mehr Details hier: http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

So die Antwort „Nein, Sie kann nicht

in Theads Pool“erstellt besondere Priorität für Thread angeben Als allgemeiner Threadings ich

Sie bereits wissen, über Thread.Priority Eigenschaft wetten
+3

Ja, ich weiß über Thread.Priority. Aber ich wollte nur wissen, ob es mit Task Factory möglich war, Objekte von Thread zu verwenden. – Moon

+0

Am ersten Link ist es eine Beschreibung, die besagt, dass es mit Task Factory nicht möglich ist.Jedenfalls muss ich nie die Priorität für Threads aus dem Pool ändern und nicht 100% sicher, dass es die Wahrheit ist. – zerkms

5

Überprüfen Sie zum Festlegen der Priorität mit Task die benutzerdefinierten Taskplaner, die von Microsoft Experte Stephen Toub in this MSDN blog post beschrieben werden. Für weitere Details, verpassen Sie nicht die Links zu den vorherigen zwei Posts, die er im ersten Satz erwähnt.

Für Ihr Problem klingt es so, als ob Sie sich vielleicht die ansehen möchten.

15

Die Threadpriorität für Tasks kann innerhalb der eigentlichen Methode festgelegt werden, die den Task ausführt. Vergessen Sie jedoch nicht, die Priorität wiederherzustellen, wenn Sie fertig sind, um Probleme zu vermeiden.

Also zuerst die Aufgabe starten:

new TaskFactory().StartNew(StartTaskMethod);

Stellen Sie dann den Thread-Priorität:

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

Wenn die Priorität zu ändern, bedenken Sie dieses: Why *not* change the priority of a ThreadPool (or Task) thread?

+6

Dieser Ansatz scheint mir gefährlich. Ist das nicht die Priorität für einen der ThreadPool-Threads? Sie wissen nicht, wo dieser Thread als nächstes verwendet wird. – Brannon

+0

@ Brannon, die Änderung der Priorität über den Taskplaner wird einen ähnlichen Effekt haben, nehme ich an. Im Allgemeinen ändern Sie die Priorität überhaupt nicht, aber wenn Sie dies tun müssen, gibt es keinen Unterschied wie Sie es tun. –

+1

@net_prog, ich denke du verstehst Brannon nicht. Ein Thread aus einem Thread-Pool wird erneut verwendet. Wenn Sie das nächste Mal einen Thread erneut verwenden möchten, müssen Sie die richtige Priorität sicherstellen. Standardverhalten ist, Thread in normaler Priorität zu haben. Wenn Sie eine Drittanbieter-Bibliothek verwenden, die den Thread-Pool verwendet, können Sie Probleme bekommen, wenn die Priorität nicht wie erwartet ist. –

41

Wie andere haben erwähnt, müssen Sie einen benutzerdefinierten Scheduler für Ihre Aufgabe angeben. Leider gibt es keinen geeigneten integrierten Scheduler.

Sie könnten für die ParallelExtensionsExtras gehen, mit denen Glenn verbunden ist, aber wenn Sie etwas Einfaches wollen, das einfach direkt in Ihren Code eingefügt werden kann, versuchen Sie Folgendes. Verwenden Sie wie folgt aus:

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

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

Hinweise:

  • Arbeitsthreads alle Hintergrund-Threads sind, so wichtige Aufgaben sollten nicht mit diesen Scheduler geplant werden; nur diejenigen, die verworfen werden können, wenn der Prozess herunterfährt
  • angepasst von an implementation by Bnaya Eshet
  • Ich verstehe nicht jede Überschreibung; gehen Sie einfach mit Bnayas Wahlen für MaximumConcurrencyLevel, GetScheduledTasks und TryExecuteTaskInline.
+5

Es erscheint dies hat jetzt einen (nicht im Abspann) Platz auf GitHub, mit der Lizenz geändert (wahrscheinlich nicht legal) und einige Zusätze, um mit Finalisierung/Beseitigung fertig zu werden, obwohl vielleicht nicht die AppDomain selbst untergeht (IRegisteredObject). –

+1

Wie wunderbar ausführlich, wenn Sie nur die Leichtigkeit der TaskParallelLibrary nutzen UND eine Priorität festlegen wollen ... Nichts für ungut. Danke für die Antwort. –

Verwandte Themen