Frage

Ich schreibe eine Audio-Anwendung, die mehrere Threads Klangerzeugung und einen Faden, mischt die Töne und sendet sie an die Soundkarte hat. Ich habe mehrere Möglichkeiten der Synchronisation Threads versucht, die ‚richtige‘ Art und Weise Signale und Faden sicher Warteschlangen einschließlich, aber sie waren alle zu langsam. So jetzt habe ich einen Bool für jeden Hersteller verwenden, um anzuzeigen, ob seine Warteschlange voll ist. Es scheint sehr gut zu funktionieren (5 ms für 32 Threads Latenz) aber ist es sicher, es auf diese Weise zu tun?

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

Die Produzenten wie folgt aussehen:

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

Der Verbraucher sieht wie folgt aus (genannt von einem separaten Thread von 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;
        }
War es hilfreich?

Lösung

No it is not completely safe, but you might get lucky most of the time ;-) You should be using the Interlocked methods to access the bool.

Andere Tipps

As far as I know, the .NET memory model doesn't guarantee that the changes of a variable made in one thread will be visible in another thread. You need a memory barrier there. The simplest (though not the most efficient) way to organize that is by using lock or Interlocked methods.

By the way, busy waiting is not the best method to achieve your goal. Maybe you'd like to switch to the producer-consumer model with appropriate condition variable (Monitors in C# parlance) usage?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top