线程安全的内部线程工作者

时间:2010-11-08 18:22:39

标签: c# synchronization thread-safety

我想知道如何在执行线程内做线程安全,让我通过示例解释一下:

让我说我想拥有应该一个接一个地执行的命令管道,但在我的线程中我不能等待它们。线程通常是睡眠的,如果某个命令被排队,则会等待,然后它会执行队列中的所有命令并再次进入休眠模式,直到新命令被排队。类似的东西:


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()之前调用)。知道如何使这个架构线程安全吗?

3 个答案:

答案 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);
    }