Frage

Kurz unter einem einzigen Hersteller - Einzel Verbraucher Szenario, verwenden ich ein veränderbares Objekt für die Synchronisation und Daten und Nachrichten zwischen Produzenten und Konsumenten zu überwälzen. Shared-Buffer ist ein ConcurrentQueue von Byte-Arrays. Um einen zirkularen Puffer zu implementieren und verhindern Heapfragmentierung und häufiges Objekt Swapping von GC verwenden ich eine ConcurrentBag von Byte-Arrays als recycle-Behälter für benutzten Byte-Arrays. ManualResetEventSlim für Thread-Synchronisation verwendet. Manchmal verliere ich Bezug auf Byte-Arrays in meinem Code. Unten ist eine vereinfachte Version von meinem Code, falls Sie weitere Informationen benötigen, aber ich denke, dies ist eine Routine Fehler ist, während mit einem Gewinde zu arbeiten.

MutableObject mutableObject = new MutableObject();

Producer producer = MutableObject.GetProducer();
Consumer consumer = MutableObject.GetConsumer();

Thread fork = new Thread(new ThreadStart(producer.Start));

// Forking execution path
fork.Start();
// Main thread goes here
consumer.Start();


class MutableObject()
{
    private Producer m_producer;
    private Consumer m_consumer;
    private ConcurrentBag<byte[]> m_recycleBin = new ConcurrentBag<byte[]>();
    private ConcurrentQueue<byte[]> m_sharedBuffer = new ConcurrentQueue<byte[]>();

    public Producer GetProducer()
    {
        // Keep a reference to the mutable object
        return new Producer(this);
    }

    // GetConsumer() method is just like GetProducer() method

    public void GetEmptyBuffer(out byte[] buffer)
    {
        if (!m_recycleBin.TryTake(out buffer))
            buffer = new byte[1024];
    }

    public bool Put(byte[] buffer)
    {
        m_sharedBuffer.Enqueue(buffer);
        // Set ManualResetEventSlim for consumer
    }

    public bool Get(byte[] buffer) // Consumer calls this method in a loop
    {
        m_sharedBuffer.TryDequeue(out buffer);
        // I save a reference to buffer here and pass it to recyclebin at next call like this: lastBuffer = buffer;
        // This is because buffers are passing by refrence for I should wait until it would be used by consumer.
        m_recycleBin.Add(lastBuffer);
        // Set ManualResetEventSlim for producer
    }
}

class Producer
{
    private MutableObject m_mutableObject;

    public Producer(MutableObject mutableObject)
    {
        m_mutableObject = mutableObject;
    }

    public void Start()
    {
        byte[] buffer;

        while (true)
        {
            m_mutableObject.GetEmptyBuffer(out buffer);
            m_mutableObject.Put(buffer);
        }
    }
}

Eigentlich GetEmptyBuffer() Methode erstellt häufig neue Puffer und obwohl gebrauchte Puffer in recycle-ist gespeichert sind, die recycle-ist Zahl manchmal nicht erhöhen!

War es hilfreich?

Lösung

public bool Get(byte[] buffer)

Das wäre ein wichtiger Ort sein, um eine Referenz zu verlieren. Diese Methode kann nicht wirklich geben die Puffer, die abgerufen wurde. Sie müssten die ref Stichwort, um es das Array zu lassen zurückzukehren. Kaum zu glauben, dass der echte Code alles so aussieht, es wäre einfach nicht funktionieren. Es gibt viele andere rote Fahnen, hat ConcurrentBag Faden Assoziativität, bekommt Sachen verloren, wenn Sie Verbraucher Threads on the fly zu erstellen. Sie können nicht synchronisiert Verbraucher mit einem Produzenten mit einem Manual, kann es nur auf 1 zählen.

In der Regel wird diese Optimierung ist nicht angebracht, es sei denn die Puffer sind größer als 85KB. Vertrauen Sie den Garbage Collector, es hat eine ausgezeichnete Arbeit, die ist sehr schwer zu verbessern auf.

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