Пробуждение потоков с помощью QWaitCondition



Мое приложение Qt имеет рабочий поток, который обрабатывает новые данные, когда они доступны. До сих пор рабочий поток использовал QWaitCondition для пробуждения при появлении новых данных.



Однако условие QWaitCondition запускается только тогда, когда поток активно ожидает через wait(). Однако может случиться так, что новые данные будут доступны, пока поток все еще работает, или непосредственно перед тем, как он перейдет к следующей команде wait ().



Я ищу что-то вроде CEvent в MFC, который "помнит" новое уведомление о данных в любое время и не будет ждать, если новые данные были сигнализированы с момента последнего вызова wait (). Каков наилучший способ достичь этого в Qt?



Спасибо,
Фабиан

596   2  

2 ответов:

Если какой-то другой поток может подать сигнал при поступлении новых данных, вы можете реализовать простой класс планировщика, чтобы разбудить ваш поток в нужное время (используя сигналы / слоты, как предложил @ ratchet freak):

class Data;
class Scheduler : public QObject
{
Q_OBJECT
public:

Scheduler(QTread* workerIn) : worker(workerIn) {};

Q_SLOT void OnNewData(Data* data)
{
QMutexLocker lock(&mutex);
while(worker->isRunning())
   condition.wait(&mutex);

Q_EMIT startWorker(data);
}; 

Q_SLOT void OnThreadFinished() 
{
     condition.wakeOne();
}

Q_SIGNAL void startWorker(Data* data);    

private:
QThread* worker;
QWaitCondition condition;
QMutex mutex;
};

Если во время работы worker поступает несколько значений данных, они будут должным образом помещены в очередь событий qt. Планировщик должен жить в своем собственном потоке. Сигнал startWorker должен быть подключен к соответствующему слоту в рабочем потоке, готовый слот рабочего потока должен быть подключен к Слот OnThreadFinished ().

QWaitCondition следует использовать в сочетании с QMutex

public void Worker::add(Data data)
{
    QMutexLocker lock(&mutex);
    //add data
    condition.wakeOne();
}


public void Worker::run()
{
    while(true)
    {
        Data data;
        {
            // no other thread will be able to trigger a wake while inside this block
            QMutexLocker lock(&mutex);
            if(shouldStop)return;
            while(!hasAvailable()) 
                condition.wait(&mutex);
            data = removeOne();
        }
        //do something with data;

    }
}

Таким образом, если новый пакет приходит по потоку, он не будет wait и wakeOne не будет инициирован другим потоком между проверкой в while и вызовом ожидания

Лучший вариант-использовать сигнал и слоты

Comments

    Ничего не найдено.