我是 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
中的锁定语句应仅包含对队列的访问,而不是整个处理阶段。
我不知道性能如何,但看起来你想要AutoResetEvent。
这无疑为您提供了执行您所描述的操作的最简单方法之一。测试一下,如果您发现性能是一个问题,那么就考虑另一种方法来实现它。
在我看来,您想使用生产者/消费者模式。使用阻塞队列最容易实现这一点。一旦你有了这个,那么其他一切就很容易了。您可以在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();
}
}