简体   繁体   English

BlockingQueue的QWaitCondition:当线程仍在等待时被销毁

[英]BlockingQueue's QWaitCondition: Destroyed while threads are still waiting

I've built my own blocking queue in Qt and I'm having a bit of a problem. 我在Qt中构建了自己的阻塞队列,我遇到了一些问题。 If I don't Close the queue, then I get an error in console " QWaitCondition: Destroyed while threads are still waiting ". 如果我不关闭队列,那么我在控制台“ QWaitCondition: Destroyed while threads are still waiting ”中出现错误。 On the other hand, I get an access violation exception after I close the queue (regardless if it's in the constructor or from another thread). 另一方面,我在关闭队列后得到访问冲突异常(无论它是在构造函数中还是从另一个线程)。 The exception occurs in the wait condition's wait method. 等待条件的等待方法中发生异常。

Here is my blocking queue: 这是我的阻塞队列:

#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

I'm assuming that this is happening because the thread that's waiting gets signaled after the Queue has been destroyed already and the mutex is subsequently destroyed too. 我假设这种情况正在发生,因为等待的线程在队列已经被销毁之后发出信号并且随后也会销毁互斥锁​​。 When the thread is woken up in TryDequeue , the mutex is no longer allocated so it causes an access violation exception. TryDequeue唤醒线程时,不再分配互斥锁,因此会导致访问冲突异常。 What's the best way to avoid this? 避免这种情况的最佳方法是什么?

The problem I was encountering was related to the threading approach, for more info take a look at this question: Why is QThread::finished signal not being emitted? 我遇到的问题与线程方法有关,更多信息请看这个问题: 为什么没有发出QThread :: finished信号?

The service that was using the BlockingQueue was not properly closing the thread that was waiting on the queue and it was subsequently causing the queue to be destroyed while a thread is still waiting inside the TryDequeue method. 使用BlockingQueue的服务没有正确关闭正在队列中等待的线程,并且当线程仍然在TryDequeue方法内等待时,它随后导致队列被销毁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM