我是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 :(得分: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>
个工作数据对象; AddJob
会Enqueue
一个项目,而Run
会保留Dequeue
,直到队列为空。如果这样做,Run
中的lock语句应仅包含对队列的访问,而不是整个处理阶段。
答案 1 :(得分:0)
我不知道性能,但看起来你想要AutoResetEvent。
这肯定会为您提供最简单的方法来完成您所描述的内容。测试一下,如果你发现性能是一个问题,那么就要担心另一种方法。
答案 2 :(得分: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();
}
}