3

並行Socket操作を作成するために、次のコードを作成しました。

ConcurrentQueue<byte[]> messageQueue;
ManualResetEvent resetEvent;
Thread outThread;   // -> new Thread(BeginSending);

public void BeginSending() // invoked by outThread
{
    while (true)
    {
        resetEvent.WaitOne();
        while (messageQueue.Count > 0)
        {
            byte[] msg;
            messageQueue.TryDequeue(out msg);
            // send msg via socket
        }
        resetEvent.Reset();
    }
}

public void QueueMessage(byte[] msg) // invoked by the main thread
{
    messageQueue.Enqueue(msg);
    resetEvent.Set();
}

ConcurrentQueue別のスレッドがそれを反復/デキューしている間にアイテムを追加することは危険なことですか?

私の理解では、多くの同期されたコレクションには個別に同期されたメソッドがありますがconcurrentQueue、同様のコレクションについても同じことが言えますか?
ConcurrentBag、、)ConcurrentDictionary_ConcurrentStack

4

4 に答える 4

4

ConcurrentQueue要素として格納されている配列を変更しない限り、それ自体は問題ありません。

ただし、の使用パターンManualResetEventは、より良い解決策があることを示しています。を使用するBlockingCollection<T>と、手動同期を回避できます。

于 2012-11-11T15:46:18.167 に答える
2

別のスレッドが反復/デキューしている間にConcurrentQueueにアイテムを追加することは危険なことですか?

いいえ、安全です。

于 2012-11-11T15:43:00.020 に答える
1

ConcurrentQueueは問題ありませんが、ManualResetEventは問題ありません。

public void BeginSending() // invoked by outThread
{
    while (true)
    {
        resetEvent.WaitOne();
        while (messageQueue.Count > 0)
        {
            byte[] msg;
            messageQueue.TryDequeue(out msg);
            // send msg via socket
        }

    // context change
    messageQueue.Enqueue(msg);
    resetEvent.Set();
    // context change

        resetEvent.Reset();
    }
}

このような一連のイベントにより、キューに入れられたメッセージは無視されます。他のポスターで提案されているように、BlockingCollectionを使用するか、シグナル/待機にセマフォを使用します。

于 2012-11-11T19:14:31.933 に答える
0

並行コレクションは、スレッドセーフになるように設計されています。それらを使用すると、自分で実装することで多くの問題を回避できます。

ただし、コレクション自体は同期されており、コレクション内のデータは同期されていないことに注意してください。他のスレッドに注意を払わずにコレクション内のオブジェクトを更新すると、競合状態が発生する可能性があります。

クラスのあらゆる使用法と同様に、コレクションの使用法とユースケースを理解していると役立ちます

于 2012-11-11T15:46:34.750 に答える