2016-03-21 136 views
0

的.Net標準庫中我只是用手寫下這段代碼:單一線程執行

class SingleWorkerThread 
{ 
    private static readonly ILog _logger = LogManager.GetLogger(typeof(SingleWorkerThread)); 
    public readonly BlockingCollection<Action> tasks = new BlockingCollection<Action>(); 
    private readonly Thread thread; 

    private void executeThread() 
    { 
     _logger.InfoFormat("Starting execution"); 
     Action task; 
     while((task = tasks.Take()) != null) 
     { 
      _logger.InfoFormat("About to execute a task...", task); 
      task(); 
      _logger.InfoFormat("Completed executing task"); 
     } 
     _logger.InfoFormat("Finished execution"); 
    } 

    public SingleWorkerThread() 
    { 
     thread = new Thread(executeThread); 
    } 

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

    public void Terminate() 
    { 
     tasks.Add(null); 
    } 

    public void AddTask(Action a) 
    { 
     tasks.Add(a); 
    } 

    public void Join() 
    { 
     // Wait up to 2 seconds for thread to terminate. 
     thread.Join(2000); 
    } 
} 

我使用它,以確保任務的某一類的所有執行總是由一個單獨的線程來完成。

我想避免「重新發明輪子」,如果可能的話 - 是否有一個標準的.Net「隊列消耗線程」模塊,我可以用它來代替上述模塊?

如果沒有,在我剛剛發佈的代碼中是否有任何「陷阱」(即錯誤)?

+1

A 「單個線程的線程池」 似乎有點矛盾。 :) – CodingGorilla

+3

「我正在使用它來確保某個類別任務的所有執行總是由單個線程完成的。」爲什麼? –

+0

我認爲你的方法沒問題(但是我會使用'Thread' +'tasks.GetConsumingEnumerable()'和'tasks.CompleteAdding')而不是添加null動作來終止任務' – Eser

回答

0

我會爲此使用Microsoft的Reactive Framework(NuGet「Rx-Main」)。

這是基本的代碼:

class SingleWorkerThread : IDisposable 
{ 
    private Subject<Action> _subject; 
    private IScheduler _scheduler; 
    private IDisposable _subscription; 

    private static readonly ILog _logger = LogManager.GetLogger(typeof(SingleWorkerThread)); 

    public SingleWorkerThread() 
    { 
     _scheduler = new EventLoopScheduler() 
     _subject = new Subject<Action>(); 
     _subscription = 
      _subject 
       .ObserveOn(_scheduler) 
       .Subscribe(task => 
       { 
        _logger.InfoFormat("About to execute a task...", task); 
        task(); 
        _logger.InfoFormat("Completed executing task"); 
       }); 
    } 

    public void Dispose() 
    { 
     _subscription.Dispose(); 
    } 

    public void AddTask(Action Action) 
    { 
     _subject.OnNext(Action); 
    } 
}