2010-11-15 35 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)的用法?

相關問題