2010-10-01 32 views
28

下面的代碼將啓動一個新線程來完成這項工作。有什麼辦法可以控制該線程的優先級?降低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 
}); 

回答

6

這是「不能做」,當你決定是否使用線程池或不;-)

更多細節在這裏之一:http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

因此,答案是「不,你不能在Theads池」

創建的線程指定特定優先級作爲普通螺紋我敢打賭,你已經知道Thread.Priority財產

+3

是的我知道Thread.Priority。但我只想知道是否可以使用Task Factory而不是使用Thread對象。 – Moon 2010-10-01 04:59:01

+0

在第一個鏈接中,描述說Task Factory是不可能的。無論如何,我永遠不需要改變線程池的優先級,也不會100%確定它是真實的。 – zerkms 2010-10-01 05:00:52

5

要設置優先級爲Task,請查看Microsoft專家Stephen Toub中描述的自定義任務計劃程序this MSDN blog post。有關詳細信息,請不要錯過他在第一句中提到的前兩個帖子的鏈接。

對於你的問題,這聽起來像你可能想看看QueuedTaskScheduler

15

任務的線程優先級可以在執行任務的實際方法中設置。但是,一旦完成後不要忘記恢復優先級,以避免出現問題。

所以首先啓動任務:

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

當更改優先級,請記住這一點:Why *not* change the priority of a ThreadPool (or Task) thread?

+6

這種方法對我來說似乎很危險。是不是在其中一個ThreadPool線程上設置優先級?你不知道接下來將使用哪個線程。 – Brannon 2013-02-19 23:26:02

+0

@Brannon,通過任務計劃程序更改優先級,我會想到類似的效果。一般來說,你根本不會改變優先級,但是如果你需要這樣做,你的工作方式並沒有什麼不同。 – 2013-04-19 14:08:29

+1

@net_prog,我想你不明白Brannon點。來自線程池的線程被重新使用。下一次你想重新使用一個線程時,你必須確保適當的優先級。默認行爲是讓線程處於正常優先級。我使用了使用線程池的第三方庫,如果優先級不符合預期,則可能陷入麻煩。 – 2013-12-11 19:13:58

41

正如其他有上面提到,你需要指定一個自定義調度程序來完成你的任務。不幸的是,沒有合適的內置調度器。

你可以去Glenn鏈接的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 
    } 
} 

注:

  • 工作線程都是後臺線程,所以重要的任務不應該使用這個調度計劃;只有那些過程關閉時可以丟棄的部分
  • 改編自an implementation by Bnaya Eshet
  • 我不完全理解每一個覆蓋;剛剛與Bnaya的MaximumConcurrencyLevel,GetScheduledTasksTryExecuteTaskInline的選擇。
+5

看起來像這樣現在在GitHub上有一個(uncredited)的地方,許可證發生了變化(可能不合法),還有一些用於處理終結/處置的補充,儘管可能不是AppDomain本身出現故障(IRegisteredObject)。 – 2014-03-06 18:35:19

+1

如果你只是想利用TaskParallelLibrary的容易性並設置一個優先級,這是多麼奇妙......儘管沒有冒犯性。感謝你的回答。 – 2015-11-20 08:28:07