2010-08-14 103 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(); 
    } 
}