2010-09-30 98 views
1

我試圖使用並行任務庫揭開序幕像這樣的一些任務:並行任務的建議

var workTasks = _schedules.Where(x => x.Task.Enabled); 
_tasks = new Task[workTasks.Count()];  
_cancellationTokenSource = new CancellationTokenSource();  
_cancellationTokenSource.Token.ThrowIfCancellationRequested();  

int i = 0;  
foreach (var schedule in _schedules.Where(x => x.Task.Enabled)) 
{ 
    _log.InfoFormat("Reading task information for task {0}", schedule.Task.Name);  
    if(!schedule.Task.Enabled) 
    { 
     _log.InfoFormat("task {0} disabled.", schedule.Task.Name);  
     i++;  
     continue; 
    } 

    schedule.Task.ServiceStarted = true;  
    _tasks[i] = Task.Factory.StartNew(() => 
      schedule.Task.Run() 
     , _cancellationTokenSource.Token);       
    i++;  
    _log.InfoFormat("task {0} has been added to the worker threads and has been started.", schedule.Task.Name); 
} 

我想這些任務睡覺,然後醒來每隔5分鐘,做自己的東西,在我的日程安排對象,它的運行方法,使用了Thread.Sleep的時刻是傳遞到StartNew作爲這樣一個變量的操作:

_tasks[i] = Task.Factory.StartNew(() => 
     schedule.Task.Run() 
    , _cancellationTokenSource.Token); 

我聽說了Thread.Sleep是一個不好解決這個。任何人都可以推薦更好的方法?

回答

0

不好的解決辦法是Task在這裏。 Task應該用於短期生活操作,如異步IO。如果你想控制任務的生命週期,你應該使用Thread並儘可能地睡覺,因爲Thread是單獨的,但Task s在共享的線程池中輪換。

+0

您可以指定TaskCreationOptions.LongRunning,創建一個新的線程,而不是使用線程池的任務。 – 2012-08-20 09:37:15

2

根據我的理解,Thread.Sleep通常是不好的,因爲它強制將內存全部從內存中移出,即使沒有必要。在大多數情況下這不會成爲大問題,但這可能是性能問題。

我在使用這個片段,而不是習慣:

new System.Threading.EventWaitHandle(false, EventResetMode.ManualReset).WaitOne(1000); 

適合在同一行,而不是過於複雜 - 它創建一個永遠不會被設置的事件句柄,然後等待在繼續之前的整個超時時間。

無論如何,如果你只是想每5分鐘重複一次,一個更好的方法可能是使用一個計時器。你甚至可以使一個類來包裝整齊的一切,如果你重複的工作方法已經分解出來:

using System.Threading; 
using System.Threading.Tasks; 
public class WorkRepeater 
{ 
    Timer m_Timer; 

    WorkRepeater(Action workToRepeat, TimeSpan interval) 
    { 
     m_Timer = new System.Timers.Timer((double)Interval.Milliseconds); 
     m_Timer.Elapsed += 
      new System.Timers.ElapsedEventHandler((o, ea) => WorkToRepeat()); 
    } 

    public void Start() 
    { 
     m_Timer.Start(); 
    } 

    public void Stop() 
    { 
     m_Timer.Stop(); 
    } 
}