我想知道如何在执行线程内做线程安全,让我通过示例解释一下:
让我说我想拥有应该一个接一个地执行的命令管道,但在我的线程中我不能等待它们。线程通常是睡眠的,如果某个命令被排队,则会等待,然后它会执行队列中的所有命令并再次进入休眠模式,直到新命令被排队。类似的东西:
public void Enqueue(ICommand command)
{
this.queue.Enqueue(command);
this.synchroHandler.Set();
}
private void Pipeline()
{
while (true)
{
this.synchroHandler.WaitOne();
while (this.queue.Count > 0)
{
ICommand command = this.queue.Dequeue();
command.Execute();
}
// what if command will be enqueued between previous command - HERE
// ... and this command HERE
this.synchroHandler.Reset();
}
}
public void Main()
{
this.queue = new ThreadSafeQueue<ICommand>();
this.computionHandler = new ManualResetEvent(false);
Thread thread = new Thread(new ThreadStart(this.Pipeline));
thread.Start();
// start adding commands to pipeline
this.Enqueue(command1);
this.Enqueue(command2);
...
}
假设我的队列实现是线程安全的,所以this.queue.Count,this.queue.Enqueue和this.queue.Dequeue使用相同的锁。如果在“}”和this.synchroHandler.Reset()之间调用公共Enqueue(),则示例中显示的ss;即使在队列中有一个项目,线程也会睡觉(this.synchroHandler.Set()将在this.synchroHandler.Reset()之前调用)。知道如何使这个架构线程安全吗?
答案 0 :(得分:2)
在BlockingCollection<T>
命名空间中查看System.Collections.Concurrent,线程安全的生产者 - 消费者。
答案 1 :(得分:0)
你应该在WaitOne()之后立即调用this.synchroHandler.Reset()。
因此,如果在重置之前调用Queue,则将进入while循环,如果在检查queue.Count后调用它,则下次调用WaitOne()时,它将立即返回并进入while循环。
答案 2 :(得分:0)
你可以把它改成旋转吗?因此,每隔10毫秒,线程就会唤醒并检查队列是否有项目,否则再次进入休眠状态。
while (true)
{
while (this.queue.Count > 0)
{
ICommand command = this.queue.Dequeue();
command.Execute();
}
Thread.Sleep(10);
}