2012-06-11 153 views
4

對於我正在處理的遊戲,我想將音頻放在另一個線程中,這樣我就可以排列聲音並立即播放它們。我在該線程中使用的代碼看起來像這樣線程和睡眠()

private void _checkForThingsToPlay() 
{ 
    while (true) 
    { 
     if (_song != null) 
     { 
      _playSong(_song); 
      _song = null; 
     } 

     while (_effects.Count > 0) 
      _playSfx(_effects.Dequeue()); 

     Thread.Sleep(100); 
    } 
} 

這是異步運行並且工作得很好。但是,如果沒有進入休眠狀態,它會在CPU上佔用整個內核。我的問題是,sleep()是一種降低CPU使用率的有效方法,還是有更好的方法來做到這一點?我的朋友和我覺得這是一個快速入侵。

+0

如果您可以使用Reactive Framework(Rx),那麼您會發現大量的「調度程序」用於對異步操作進行排序。 – Enigmativity

回答

5

這就是所謂的producer-consumer problem,可以很容易地解決。如果您使用.NET 4,請嘗試BlockingCollectionMSDN page中有一個很好的示例代碼。

注意這條線中的示例代碼:

while (true) Console.WriteLine(bc.Take()); 

這將實際上阻止(沒有CPU週期被浪費),直到有東西消耗

+0

我將所有的隊列交換爲BlockingCollections,並將我的循環設置爲類似於您的循環(我剛剛更改了我的dequeue()以獲取())。不過,我的CPU使用率仍然很高,所以我認爲它不會阻塞。除了調用Take()之外,還有更多嗎? – MGZero

+0

沒關係,別的東西在吃掉CPU。音頻線程現在阻塞很好。 – MGZero

+0

很高興你解決了它。 –

7

while(true)循環中使用Thread.Sleep()通常是一個壞習慣。它看起來像是有一個隊列用於播放聲音效果,並且您希望「音頻線程」在播放隊列時立即播放這些效果。這聽起來像是producer/consumer queue。有多種方式可以在C#中構建這樣一個隊列。您可以使用Monitor.Wait()Monitor.Pulse()或者您可以使用AutoResetEvent對象。

在.NET 4中,您也可以使用BlockingCollection

順便說一下,在threading in C#中有一個非常好的在線介紹,它描述了很多常見的線程/同步方案和最佳實踐。