2010-11-15 109 views
4

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

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; 
    } 
} 

消费者看起来像这样(由n音讯一个单独的线程调用):

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; 
     } 
+0

你是如何设置isPlaying变量的? – marcind 2010-11-15 01:03:51

+0

@marcind当用户按下停止按钮时,isPlaying设置为false – 2010-11-15 01:14:43

回答

4

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

+1

+1我还会建议联锁方法。该变量也应该标记为“volatile”。 – casablanca 2010-11-15 01:04:31

+0

不幸的是,互联网在.NET 3.5中不可用。但是不是设置一个布尔原子? – 2010-11-15 01:22:30

+0

@casablanca谢谢,这似乎正是我需要的 – 2010-11-15 01:23:54

5

据我所知,.NET内存模型并不能保证在一个线程中创建的变量的更改将在另一个线程中可见。那里你需要一个内存barrier。最简单的(尽管不是最有效的)方法是使用lockInterlocked方法。

顺便说一句,忙等待并不是达到目标的最佳方法。也许你想切换到producer-consumer model与适当的条件变量(用C#说法Monitor s)的用法?