4

サウンドを生成する複数のスレッドと、サウンドをミキシングしてサウンドカードに送信する1つのスレッドを持つオーディオアプリケーションを作成しています。シグナルやスレッドセーフキューなど、スレッドを「正しい」方法で同期するいくつかの方法を試しましたが、すべて遅すぎました。そこで、各プロデューサーにブール値を使用して、キューがいっぱいかどうかを示します。非常にうまく機能しているようですが(32スレッドで5ミリ秒の遅延)、この方法で安全に実行できますか?

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メモリモデルは、あるスレッドで行われた変数の変更が別のスレッドで表示されることを保証するものではありません。そこにはメモリバリアが必要です。lockまたはメソッドを使用して整理するための最も簡単な(最も効率的ではありませんが)Interlocked方法。

ちなみに、ビジーウェイトはあなたの目標を達成するための最良の方法ではありません。適切な条件変数(C#の用語ではs)を使用する生産者/消費者モデルに切り替えたいと思いませんか?Monitor

于 2010-11-15T01:24:06.980 に答える
4

いいえ、完全に安全というわけではありませんが、ほとんどの場合幸運になる可能性があります;-)ブール値にアクセスするにはInterlockedメソッドを使用する必要があります。

于 2010-11-15T01:02:32.320 に答える