4

我正在编写一个音频应用程序,它有多个产生声音的线程和一个混合声音并将它们发送到声卡的线程。我尝试了几种以“正确”方式同步线程的方法,包括信号和线程安全队列,但它们都太慢了。所以现在我为每个生产者使用一个布尔值来指示它的队列是否已满。它似乎工作得很好(32 个线程的 5ms 延迟)但是这样做安全吗?

class PlayThreadParameters
{
    public Queue<Samples> queue;
    public bool isOutputQueueFull;
}

生产者看起来像这样:

  public void PolyPlayThread(object o)
    {
        var playThreadParameters = (PlayThreadParameters)o;
        while (isPlaying)
        {
            while (playThreadParameters.isOutputQueueFull)
            {
                if (!isPlaying)
                    return;
                Thread.Sleep(1);
            }

        ... //fill output queue

        playThreadParameters.isOutputQueueFull = true;
    }
}

消费者看起来像这样(Naudio 从单独的线程调用):

public override int Read(byte[] array, int offset, int count)
        {

                for (int v = 0; v < playThreadParameters.Length; v++)
                    while (!playThreadParameters[v].isOutputQueueFull)
                    {
                        if (!isPlaying)
                            return 0;
                        Thread.Sleep(1); 
                    }

                ... //mix the samples from the outputqueues

                for (int v = 0; v < playThreadParameters.Length; v++)
                    playThreadParameters[v].isOutputQueueFull =false;

            return count;
        }
4

2 回答 2

5

据我所知,.NET 内存模型不能保证在一个线程中对变量所做的更改将在另一个线程中可见。你需要一个内存屏障。最简单(虽然不是最有效)的组织方式是使用lockorInterlocked方法。

顺便说一句,忙碌的等待并不是实现目标的最佳方法。也许您想切换到具有适当条件变量(C# 用语中的 s )用法的生产者-消费者模型?Monitor

于 2010-11-15T01:24:06.980 回答
4

不,它不是完全安全的,但大多数时候你可能会很幸运;-) 你应该使用Interlocked方法来访问 bool。

于 2010-11-15T01:02:32.320 回答