0

簡単に言えば、単一のプロデューサーと単一のコンシューマーのシナリオの下で、プロデューサーとコンシューマーの間で同期とデータとメッセージの受け渡しに可変オブジェクトを使用しました。共有バッファはConcurrentQueueバイト配列です。循環バッファーを実装し、ヒープの断片化と頻繁なオブジェクトのスワップを防ぐために、使用済みバイト配列のごみ箱としてバイト配列を使用しましたGC。スレッドの同期に使用されます。コード内のバイト配列への参照が失われることがあります。以下は、詳細が必要な場合に備えて、私のコードの簡略化されたバージョンですが、これはスレッドを操作する際の日常的な間違いだと思います。ConcurrentBagManualResetEventSlim

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

実際GetEmptyBuffer()、メソッドは頻繁に新しいバッファを作成し、使用されたバッファはごみ箱に保存されますが、ごみ箱の数が増えないことがあります。

4

1 に答える 1

2
public bool Get(byte[] buffer)

これは、参照を失う明らかな場所の 1 つです。このメソッドは、取得したバッファを実際に返すことはできません。配列を返すようにするには、 refキーワードを使用する必要があります。実際のコードがこのように見えるとは信じがたく、まったく機能しません。他にも多くの危険信号があります。ConcurrentBag にはスレッド結合性があり、その場でコンシューマ スレッドを作成するとデータが失われます。ManualResetEvent を使用してコンシューマーをプロデューサーと同期することはできません。1 までしかカウントできません。

一般に、バッファーが 85KB を超えない限り、この最適化は不適切です。ガベージ コレクターを信頼してください。改善するのが非常に難しい優れた仕事をします。

于 2010-10-25T21:02:44.050 に答える