2010-10-01 17 views
28

un codice come di seguito avvierà una nuova discussione per eseguire il lavoro. C'è un modo per controllare la priorità di quel thread?priorità inferiore della stringa Task.Factory.StartNew

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

risposta

6

Questo è uno dei "non fare" quando si decide se utilizzare pool di thread o no ;-)

Maggiori dettagli qui: http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

Quindi la risposta è: "No, non è possibile specificare una particolare priorità per thread creato in Theads Pool"

Come di filettature generali Scommetto che già si conosce Thread.Priority proprietà

+3

Sì, so di Thread.Priority. Ma volevo solo sapere se era possibile con Task Factory invece di usare gli oggetti di Thread. – Moon

+0

Al primo collegamento è la descrizione che dice che non è possibile con Task Factory.Ad ogni modo non ho mai bisogno di cambiare priorità per i thread del pool e non sono sicuro al 100% che sia vero. – zerkms

5

Per l'impostazione della priorità con Task, controllare i programmi di pianificazione delle attività personalizzati descritti dall'esperto Microsoft Stephen Toub in this MSDN blog post. Per ulteriori dettagli, non perdere i link ai precedenti due post che menziona nella prima frase.

Per il tuo problema, sembra che potresti voler dare un'occhiata allo QueuedTaskScheduler.

15

La priorità del thread per Attività può essere impostata all'interno del metodo effettivo che esegue l'attività. Ma non dimenticare di ripristinare la priorità una volta che hai finito per evitare problemi.

Quindi, prima avviare il Task:

new TaskFactory().StartNew(StartTaskMethod);

quindi impostare la priorità del 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; 
    } 
} 

Quando si cambia la priorità, tenere a mente questo: Why *not* change the priority of a ThreadPool (or Task) thread?

+6

Questo approccio mi sembra pericoloso. Non è quella che imposta la priorità su uno dei thread ThreadPool? Non sai dove verrà utilizzato quel thread in seguito. – Brannon

+0

@Brannon, la modifica della priorità tramite l'Utilità di pianificazione avrà un effetto simile, suppongo. In generale non si cambia affatto la priorità, ma se si richiede di farlo, non vi è alcuna differenza nel modo in cui si fa. –

+1

@net_prog, penso che tu non capisca il punto Brannon. Una discussione da un pool di thread è fatta per essere riutilizzata. La prossima volta che vorrete riutilizzare un thread, dovrete garantire la priorità corretta. Il comportamento predefinito è avere thread in priorità normale. Se si utilizza una libreria di terze parti che utilizza il pool di thread, è possibile che si verifichi un problema se la priorità non è quella prevista. –

41

come altri hanno menzionato, è necessario specificare un programma di pianificazione personalizzato per andare con il vostro compito. Sfortunatamente non esiste un programmatore incorporato adatto.

Si potrebbe optare per ParallelExtensionsExtras a cui è collegato Glenn, ma se si desidera qualcosa di semplice da incollare nel codice, provare quanto segue. Utilizzare questo modo:

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

Il codice:

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

Note:

  • i thread di lavoro sono tutti i thread in background, in modo da compiti importanti non dovrebbero essere programmate utilizzando questo scheduler; solo quelli che possono essere scartati se il processo si arresta
  • adattato da an implementation by Bnaya Eshet
  • Non capisco completamente ogni intervento; solo andando con le scelte di Bnaya per MaximumConcurrencyLevel, GetScheduledTasks e TryExecuteTaskInline.
+5

Sembra questo ora ha un posto (non accreditato) su GitHub, con la licenza modificata (probabilmente non legale) e alcune aggiunte per affrontare la finalizzazione/eliminazione, anche se forse non lo stesso AppDomain sta andando giù (IRegisteredObject). –

+1

Che meraviglia se si vuole solo usare la facilità della TaskParallelLibrary E impostare una priorità ... Senza offesa però. Grazie per la risposta. –

Problemi correlati