4

Qtで独自のブロッキングキューを作成しましたが、少し問題があります。キューを閉じないと、コンソール" QWaitCondition: Destroyed while threads are still waiting"でエラーが発生します。一方、キューを閉じた後、アクセス違反の例外が発生します(コンストラクターにあるか、別のスレッドにあるかに関係なく)。例外は、待機条件の待機メソッドで発生します。

これが私のブロッキングキューです:

#ifndef BLOCKING_QUEUE_H
#define BLOCKING_QUEUE_H

#include <QObject>
#include <QSharedPointer>
#include <QWaitCondition>
#include <QMutex>
#include <queue>

namespace Concurrency
{
    template<typename Data>
    class BlockingQueue
    {
    private:
        QMutex _mutex;
        QWaitCondition _monitor;
        volatile bool _closed;
        std::queue<QSharedPointer<Data>> _queue;

    public:
        BlockingQueue()
        {
            _closed = false;
        }

        ~BlockingQueue()
        {
            Close(); // When this is enabled, I get an access violation exception in TryDequeue
        }

        void Close()
        {
            QMutexLocker locker(&_mutex);
            if(!_closed)
            {
                _closed = true;
                _queue.empty();
                _monitor.wakeAll();
            }
        }

        bool Enqueue(QSharedPointer<Data> data)
        {
            QMutexLocker locker(&_mutex);

            // Make sure that the queue is not closed
            if(_closed)
            {
                return false;
            }

            _queue.push(data);

            // Signal all the waiting threads
            if(_queue.size()==1)
            {
                _monitor.wakeAll();
            }

            return true;
        }

        bool TryDequeue(QSharedPointer<Data>& value, unsigned long time = ULONG_MAX)
        {
            QMutexLocker locker(&_mutex);

            // Block until something goes into the queue
            // or until the queue is closed
            while(_queue.empty())
            {
                if(_closed || !_monitor.wait(&_mutex, time)) // <-- Access violation if I call close in the destructor
                {
                    return false;
                }
            }

            // Dequeue the next item from the queue
            value = _queue.front();
            _queue.pop();
            return true;
        }
    };
}
#endif BLOCKING_QUEUE_H

キューがすでに破棄された後、待機中のスレッドが通知され、その後ミューテックスも破棄されるため、これが発生していると思います。スレッドがでウェイクアップされるTryDequeueと、ミューテックスは割り当てられなくなるため、アクセス違反の例外が発生します。これを回避するための最良の方法は何ですか?

4

1 に答える 1

0

私が遭遇した問題は、スレッディングアプローチに関連していました。詳細については、この質問を参照してください。QThread::finishedシグナルが発行されないのはなぜですか。

を使用していたサービスは、キューで待機していたスレッドを適切に閉じていませんでした。その後、メソッドBlockingQueue内でスレッドが待機している間にキューが破棄されていました。TryDequeue

于 2012-11-19T22:31:49.117 に答える