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