2010-08-14 95 views
1

我是新來的多線程在C#中,並在所有線程的東西混淆。 這裏就是我想有:發信號通知睡眠線程

public class TheClass 
{ 
    Thread _thread; 
    bool _isQuitting; 
    bool _isFinished; 
    object jobData; 
    public void Start() 
    { 
     jobData = new object(); 
     _thread = new Thread(new ThreadStart(Run)); 
     _thread.Start(); 
    } 
    private void Run() 
    { 
     while (!_isQuitting) 
     { 
      lock (jobData) // or should i use mutex or monitor? 
      { 
       DoStuff(); 
      } 
      // sleep till get triggered 
     } 
     DoCleanupStuff(); 
     _isFinished = true; 
    } 

    public void AddJob(object param) 
    { 
     jobData = param; 
     //wake up the thread 
    } 
    public void Stop() 
    { 
     _isQuitting = true; 
     //wake up & kill the thread 
     //wait until _isFinished is true 
     //dispose the _thread object 
    } 
} 
在這個類

,什麼是最有效的方法來實現註釋掉短語和整體性能?

+0

就在幾個意見:①你'jobData'對象最初是空的,所以如果用戶調用'AddJob',它崩潰之前調用'Run'。爲了解決這個問題,你可以把'object jobdata;'改成'object jobdata = new object();'。 ②'Run'方法似乎根本沒有使用它的參數,所以你可以刪除它並使用'ThreadStart'而不是'ParameterizedThreadStart'。 – Timwi 2010-08-14 23:35:39

+0

編輯,謝謝。 – Slantroph 2010-08-14 23:39:23

回答

0

我不知道性能,但它看起來像你想AutoResetEvent

這當然給你一個最簡單的方法來做你所描述的。測試一下,如果你發現性能是一個問題,那麼擔心另一種方式來做到這一點。

2

考慮使用Monitor.Wait()Monitor.Pulse()

例如:

object locker = new object(); 

private void Run() 
{ 
    while (!_isQuitting) 
    { 
     lock (locker) 
     { 
      Monitor.Wait(locker); 
      DoStuff(jobData); 
     } 
    } 
    DoCleanupStuff(); 
} 

public void AddJob(object param) 
{ 
    // Obtain the lock first so that you don’t 
    // change jobData while the thread is processing it 
    lock (locker) 
    { 
     jobData = param; 
     Monitor.Pulse(locker); 
    } 
} 

public void Stop() 
{ 
    lock (locker) 
    { 
     _isQuitting = true; 
     Monitor.Pulse(locker); 
    } 

    // Wait for the thread to finish — no need for _isFinished 
    _thread.Join(); 
} 

但是,請注意,在我的代碼,你仍然只有一個jobData對象 - 其後果在於AddJob()將等待當前作業完成處理。這可能不是你想要的。也許你應該有一個Queue<T>作業數據對象; AddJobEnqueue一個項目和Run將保持Dequeue直到隊列爲空。如果這樣做,Run中的鎖定語句應該只包含對隊列的訪問,而不是整個處理階段。

0

它看起來像我想要使用生產者/消費者模式。這是最容易使用阻塞隊列完成的。一旦你有了,那麼一切都很簡單。你可以找到一個實現here或者你可以使用4.0中可用的BlockingCollection類。

注:爲簡潔起見,省略了硬化代碼。

public class TheClass 
{ 
    private Thread m_Thread; 
    private BlockingCollection<object> m_Queue = new BlockingCollection<object>(); 
    private CancellationTokenSource m_Cancellation = new CancellationTokenSource(); 

    public void Start() 
    { 
     m_Thread = new Thread(new ThreadStart(Run)); 
     m_Thread.IsBackground = true; 
     m_Thread.Start(); 
    } 

    private void Run() 
    { 
     while (true) 
     { 
      try 
      { 
       object job = m_Queue.Take(m_Cancellation.Token); 
      } 
      catch (OperationCanceledException) 
      { 
       break; 
      } 
     } 
    } 

    public void AddJob(object param) 
    { 
     m_Queue.Add(param); 
    } 

    public void Stop() 
    { 
     m_Cancellation.Cancel(); 
     m_Thread.Join(); 
    } 
}