发信号通知睡眠线程
问题描述:
我是新来的多线程在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
}
}
在这个类
,什么是最有效的方法来实现注释掉短语和整体性能?
答
考虑使用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>
作业数据对象; AddJob
将Enqueue
一个项目和Run
将保持Dequeue
直到队列为空。如果这样做,Run
中的锁定语句应该只包含对队列的访问,而不是整个处理阶段。
答
它看起来像我想要使用生产者/消费者模式。这是最容易使用阻塞队列完成的。一旦你有了,那么一切都很简单。你可以找到一个实现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();
}
}
就在几个意见:①你'jobData'对象最初是空的,所以如果用户调用'AddJob',它崩溃之前调用'Run'。为了解决这个问题,你可以把'object jobdata;'改成'object jobdata = new object();'。 ②'Run'方法似乎根本没有使用它的参数,所以你可以删除它并使用'ThreadStart'而不是'ParameterizedThreadStart'。 – Timwi 2010-08-14 23:35:39
编辑,谢谢。 – Slantroph 2010-08-14 23:39:23