ejemplo de una sincronización multi-hilo QT 5,9 QWaitCondition más simple

Hombre de pocas palabras, dijo, mirada a los resultados diagrama de comportamiento:

 

Ejemplos del Programa en los enlaces de abajo, por favor alabar y atención.

Para conectar     código de extracción: t7yh

QWaitCondition proporcionar algunas de las siguientes funciones:

  • esperar (QMutex * lockedMutex), desbloquea el lockedMutex mutex, y el bloque de espera de las condiciones de activación, encerrado lockedM UTEX después de la función de activación y salida 
  • wakeAll (), despierta todos los hilos en un estado de espera, el orden de la estela hilo de incertidumbre, determinados por la política de planificación del sistema operativo
  • wakeOne (), despertar un hilo en un estado de espera, que los hilos se despiertan incierto, determinado por la política de planificación del sistema operativo 

      QWaitCondition generalmente utilizado (/ consumidor productor) modelo "productor / consumidor". "Productor" generar datos, los datos de "consumidor" de uso, al conjunto de datos, mostrando los tres hilos en el ejemplo de aplicación del almacenamiento de este modelo.
 

En primer lugar, creamos dos clases, dos clases en las que qmythread.h 

#ifndef QMYTHREAD_H
#define QMYTHREAD_H

//#include    <QObject>
#include    <QThread>

class QThreadProducer : public QThread
{
    Q_OBJECT
private:
    bool    m_stop=false; //停止线程
protected:
    void    run() Q_DECL_OVERRIDE;
public:
    QThreadProducer();
    void    stopThread();
};


class QThreadConsumer : public QThread
{
    Q_OBJECT
private:
    bool    m_stop=false; //停止线程
protected:
    void    run() Q_DECL_OVERRIDE;
public:
    QThreadConsumer();
    void    stopThread();
signals:
    void    newValue(int seq,int diceValue);
};
#endif // QMYTHREAD_H

CPP correspondientes

#include    "qmythread.h"
#include    <QWaitCondition>
#include    <QTime>
#include    <QMutex>


static QMutex  mutex;
static QWaitCondition  newdataAvailable;

static int  seq=0;//序号
static int  diceValue;

QThreadProducer::QThreadProducer()
{

}

void QThreadProducer::stopThread()
{
    QMutexLocker  locker(&mutex);
    m_stop=true;
}

void QThreadProducer::run()
{
    m_stop=false;//启动线程时令m_stop=false
    seq=0;
    qsrand(QTime::currentTime().msec());//随机数初始化,qsrand是线程安全的

    while(!m_stop)//循环主体
    {
        mutex.lock();
        diceValue=qrand(); //获取随机数
        diceValue=(diceValue % 6)+1;
        seq++;
        mutex.unlock();

        newdataAvailable.wakeAll();//唤醒所有线程,有新数据了
        msleep(500); //线程休眠100ms
    }
}


void QThreadConsumer::run()
{
    m_stop=false;//启动线程时令m_stop=false
    while(!m_stop)//循环主体
    {
        mutex.lock();
        newdataAvailable.wait(&mutex);//会先解锁mutex,使其他线程可以使用mutex
        emit    newValue(seq,diceValue);
        mutex.unlock();
//        msleep(100); //线程休眠100ms
    }

}

QThreadConsumer::QThreadConsumer()
{

}

void QThreadConsumer::stopThread()
{
    QMutexLocker  locker(&mutex);
    m_stop=true;
}

 PS: Si, por QThread, QMutex no sabemos si se puede ver en la información relevante, o para centrarse en mí, me mira el uso de pre-escritura.

       QThreadConsumer para la lectura y el número de puntos de los dados, la señal de transmisión de datos bien a pasar hacia fuera de forma.
       Y el número de puntos dados variable se define como la variable compartida, por lo que dos hilos pueden tener acceso, QThreadProducer :: función run () es responsable de 500 milisegundos tirar de generación de datos falsos cada vez, despertar todos a través de la utilización de newdataAvailable.wakeAll () condición hilos de espera, QThreadConsumer :: run (), mientras que la función de bucle, es necesario en primer lugar un bloqueo de exclusión mutua en la ejecución:

       newdataAvailable.wait (y mutex);

       Esta declaración a la exclusión mutua como un parámetro de entrada, primero internamente desbloquear el mutex, otros hilos pueden utilizar el mutex, newdataAvailable en un estado de espera. Cuando QThreadProducer generar nuevos datos utilizando newdataAvailable.wakeAll () se despierta todos los hilos newdataAvailable.wait (y exclusión mutua) se bloqueará de nuevo mutex, y luego dejar de fumar estado de bloqueo para realizar las declaraciones que siguen.

      Aquí está el código de la página:

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include    <QTimer>

#include    "qmythread.h"

namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

private:
    QThreadProducer   threadProducer;
    QThreadConsumer   threadConsumer;
protected:
    void    closeEvent(QCloseEvent *event);
public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private slots:
    void    onthreadA_started();
    void    onthreadA_finished();

    void    onthreadB_started();
    void    onthreadB_finished();

    void    onthreadB_newValue(int seq, int diceValue);

    void on_btnClear_clicked();

    void on_btnStopThread_clicked();

    void on_btnStartThread_clicked();

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"

void Dialog::closeEvent(QCloseEvent *event)
{//关闭窗口
    if (threadProducer.isRunning())
    {
        threadProducer.stopThread();
        threadProducer.wait();
    }

    if (threadConsumer.isRunning())
    {
        threadConsumer.terminate(); //因为threadB可能处于等待状态,所以用terminate强制结束
        threadConsumer.wait();//
    }
    event->accept();
}

Dialog::Dialog(QWidget *parent) :  QDialog(parent),    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    connect(&threadProducer,SIGNAL(started()),this,SLOT(onthreadA_started()));
    connect(&threadProducer,SIGNAL(finished()),this,SLOT(onthreadA_finished()));

    connect(&threadConsumer,SIGNAL(started()),this,SLOT(onthreadB_started()));
    connect(&threadConsumer,SIGNAL(finished()),this,SLOT(onthreadB_finished()));

    connect(&threadConsumer,SIGNAL(newValue(int,int)),this,SLOT(onthreadB_newValue(int,int)));
}

Dialog::~Dialog()
{
    delete ui;
}

void Dialog::onthreadA_started()
{
    ui->LabA->setText("Thread Producer状态: started");
}

void Dialog::onthreadA_finished()
{
    ui->LabA->setText("Thread Producer状态: finished");
}

void Dialog::onthreadB_started()
{
    ui->LabB->setText("Thread Consumer状态: started");
}

void Dialog::onthreadB_finished()
{
    ui->LabB->setText("Thread Consumer状态: finished");
}

void Dialog::onthreadB_newValue(int seq,int diceValue)
{
    QString  str=QString::asprintf("第 %d 次掷骰子,点数为:%d",
                                   seq,diceValue);
    ui->plainTextEdit->appendPlainText(str);

    QPixmap pic;
    QString filename=QString::asprintf(":/dice/images/d%d.jpg",diceValue);
    pic.load(filename);
    ui->LabPic->setPixmap(pic);
}


void Dialog::on_btnClear_clicked()
{
    ui->plainTextEdit->clear();
}

void Dialog::on_btnStopThread_clicked()
{//结束线程
    threadProducer.stopThread();//结束线程的run()函数执行
    threadProducer.wait();//

//    threadConsumer.stopThread();//结束线程的run()函数执行
    threadConsumer.terminate(); //因为threadB可能处于等待状态,所以用terminate强制结束
    threadConsumer.wait();//

    ui->btnStartThread->setEnabled(true);
    ui->btnStopThread->setEnabled(false);
}

void Dialog::on_btnStartThread_clicked()
{//启动线程
    threadConsumer.start();
    threadProducer.start();

    ui->btnStartThread->setEnabled(false);
    ui->btnStopThread->setEnabled(true);
}

Punto a destacar aquí:

       Dos hilos comenzaron la orden no debe ser reemplazado, debe empezar threadConsumer, primero entra en el estado de espera, después de comenzar threadProducer, por lo wakeAll (cuando) threadConsumer puede responder de manera oportuna en threadProducer, de lo contrario se perderá por primera vez del niño que lanzan falsa datos.

      Al final de la rosca, si el orden de lo anterior primer hilo threadProducer final, debe terminar () para forzar el final de la rosca threadConsurner porque threadConsumer también puede estar en condición de bloqueo de esperar, no será el final de la rosca correctamente.

      Al igual que este artículo por favor haga clic en uno de los estudiantes alabanza, vamos a trabajar juntos.

Publicado 40 artículos originales · alabanza ganado 13 · vistas 5871

Supongo que te gusta

Origin blog.csdn.net/weixin_42126427/article/details/104811961
Recomendado
Clasificación