Qt5 Qthread
От: milkpot Россия  
Дата: 09.04.19 16:28
Оценка:
Здравствуйте, есть проект на Qt5.6.2 mingw-версии под WinXp, использующий нити Qt. Отладочная версия компилируется и работает.
Релиз версия аварийно завершается при попытке запуска дочерней нити.
#ifndef WORKER2_H
#define WORKER2_H

#include "mainwindow.h"
//class CreatedObject;

class WorkerThread : public QThread
{
    Q_OBJECT

    bool wait_cnd;
    bool lock_cnd;
    unsigned long one_and_a_half_hour_wait=5400000;

public:
    /*static*/ QMutex mutex;
/*static*/ QWaitCondition wtc_worker2;


    void initInnerObjects(/*const CreatedObject *cObjectsPtr*/)
    {
        //cObject=const_cast<CreatedObject *>(cObjectsPtr);
        wait_cnd=false;
        lock_cnd=false;
    }
    explicit WorkerThread(QObject *parent = Q_NULLPTR){}
    void run() Q_DECL_OVERRIDE {
        QString result;
        forever {
           //MutexLocker locker(&mutex);
            mutex.lock();

            qDebug() << "--- Worker: run() func, after lock call";
            wait_cnd=wtc_worker2.wait(&mutex,/*5000*/one_and_a_half_hour_wait);
            if(false==wait_cnd)
            {
                continue;
            }
            else if(true==wait_cnd)
            {
                result=QString(tr("--- wait_cnd is true"));
                do_send_result(result);
            }
            qDebug() << "--- wait_cnd is " << wait_cnd;
            qDebug() << "--- Worker: run() func, after wait call";
            mutex.unlock();
         }
    }
   // Q_SIGNAL void resultReady(const QString &s);
public /*slots*/:
    void launch_threadfunc()
    {
        wtc_worker2.wakeOne();
    }
signals:
    void resultReady(const QString &s);


private slots:
    void do_send_result(const QString &info_msg)
    {
        emit resultReady(info_msg);
    }
};



class CreatedObject : public QObject
{
    Q_OBJECT

    WorkerThread workerThread;
public:
   // /*static*/ QWaitCondition wtc2;

    ~CreatedObject(){
        workerThread.quit();
        workerThread.wait();
    }

    void initCreatedObject(MainWindow *window)
    {
            connect(&workerThread, &WorkerThread::resultReady, window, window->appendtoLogListBox);
            connect(&workerThread, &WorkerThread::finished, &workerThread, &QObject::deleteLater);
            workerThread.initInnerObjects();
            workerThread.start();
    }
    void wf_wake()
    {
        workerThread.launch_threadfunc();// wtc_worker2.wakeOne();
    }

};

#endif // WORKER2_H

Код который вызывает дочернюю нить
void MainWindow::button8Clicked()// pushButton_8, workerThread initialize
{
    QString str;
 //   str = QObject::tr("Path: ");
    if(b_blocking_Value_2==false)
    {
        createdObj=new CreatedObject();
        if(nullptr!=createdObj)
        {
            qDebug() << "--- Worker: button8Clicked() func, createdObj is not null call";
       //     createdObj->initCreatedObject(this);
            createdObj->initCreatedObject(this);
        }

        b_blocking_Value_2=true;
    }
}

void MainWindow::button9Clicked()// pushButton_9, workerThread wake
{
    if(b_blocking_Value_2==true)
    {
        createdObj->wf_wake();
    }
}

Приложение аварийно завершается после выполнения функции button9Clicked().
Re: Qt5 Qthread
От: SaZ  
Дата: 09.04.19 19:43
Оценка: 2 (1)
Здравствуйте, milkpot, Вы писали:

M>Здравствуйте, есть проект на Qt5.6.2 mingw-версии под WinXp, использующий нити Qt. Отладочная версия компилируется и работает.

M>Релиз версия аварийно завершается при попытке запуска дочерней нити.
M>...
M>Приложение аварийно завершается после выполнения функции button9Clicked().

createdObj где создаётся? Попробуйте все переменные инициализировать в конструкторе. А лучше даже сразу при объявлении. Но если по существу, то тут нет телепатов — давайте нормальный пример кода, который можно скомпилировать и запустить. Желательно средствами cmake под любую платформу.
Re: Qt5 Qthread
От: Igore Россия  
Дата: 10.04.19 06:55
Оценка:
Здравствуйте, milkpot, Вы писали:

M>Здравствуйте, есть проект на Qt5.6.2 mingw-версии под WinXp, использующий нити Qt. Отладочная версия компилируется и работает.

M>Релиз версия аварийно завершается при попытке запуска дочерней нити.
Чего в отладчике, чего в логах и т.д.
А из того что написано
connect(&workerThread, &WorkerThread::resultReady, window, window->appendtoLogListBox);
вызывает вопросы, почему не
connect(&workerThread, &WorkerThread::resultReady, window, &MainWindow::appendtoLogListBox);
Вообще, я бы переписал приблизительно так:
  Скрытый текст
#pragma once
#include "mainwindow.h"
//class CreatedObject;

class WorkerObject : public QObject
{
    Q_OBJECT

public:
    explicit WorkerObject(QObject *parent = Q_NULLPTR) : QObject( parent ){}
   // Q_SIGNAL void resultReady(const QString &s);
public /*slots*/:
    void launch_threadfunc(QString string)
    {
        QMetaObject::invokeMethod(this,"do_send_result",Qt::QueuedConnection,Q_ARG(QString,string));
    }
signals:
    void resultReady(const QString &s);


public slots:
    void do_send_result(const QString &info_msg)
    {
        emit resultReady(info_msg);
    }
};


class CreatedObject : public QObject
{
    Q_OBJECT

    QThread workderThread;
    WorkerObject workerObject;
    
public:
   // /*static*/ QWaitCondition wtc2;

    ~CreatedObject(){
        workerThread.quit();
        workerThread.wait();
    }

    void initCreatedObject()
    {
            workerObject.moveToThread(&workderThread);
            workerThread.start();
    }
    void wf_wake()
    {
        workerThread.launch_threadfunc("should return from thread");// wtc_worker2.wakeOne();
    }

};


MainWindow::MainWindow() 
    : QMainWindow()
    , createdObj( new CreatedObject( this ) )
{
    connect(&createdObj, &WorkerObject::resultReady, this, &MainWindow::appendtoLogListBox);
    createdObj->initCreatedObject();
}

void MainWindow::button8Clicked()// pushButton_8, workerThread initialize
{
    QString str;
 //   str = QObject::tr("Path: ");
    if(b_blocking_Value_2==false)
    {
            qDebug() << "--- Worker: button8Clicked() func, createdObj is not null call";
       //     createdObj->initCreatedObject(this);
        b_blocking_Value_2=true;
    }
}

void MainWindow::button9Clicked()// pushButton_9, workerThread wake
{
    if(b_blocking_Value_2==true)
    {
        createdObj->wf_wake();
    }
}
Отредактировано 10.04.2019 8:58 Igore . Предыдущая версия . Еще …
Отредактировано 10.04.2019 7:06 Igore . Предыдущая версия .
Re: Qt5 Qthread
От: Skorodum Россия  
Дата: 10.04.19 09:27
Оценка: 2 (1) +1
Здравствуйте, milkpot, Вы писали:

Выделил. Из-за continue mutex.unlock не вызывается, используйте QMutexLocker.
M>
M>    void run() Q_DECL_OVERRIDE {
M>        QString result;
M>        forever {
M>           //MutexLocker locker(&mutex);
M>            mutex.lock();

M>            qDebug() << "--- Worker: run() func, after lock call";
M>            wait_cnd=wtc_worker2.wait(&mutex,/*5000*/one_and_a_half_hour_wait);
M>            if(false==wait_cnd)
M>            {
M>                continue;
 M>            }
M>            else if(true==wait_cnd)
M>            {
M>                result=QString(tr("--- wait_cnd is true"));
M>                do_send_result(result);
M>            }
M>            qDebug() << "--- wait_cnd is " << wait_cnd;
M>            qDebug() << "--- Worker: run() func, after wait call";
M>            mutex.unlock();
M>         }
M>    }
M>

M>Приложение аварийно завершается после выполнения функции button9Clicked().

Вот ваш пример нормально отредактированный и работающий:

#include <QCoreApplication>
#include <QDebug>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>
#include <QTimer>
#include <QMutexLocker>

class WorkerThread : public QThread {
    Q_OBJECT

    constexpr static unsigned long waitPeriod = 500;

public:
    QMutex mutex;
    QWaitCondition waitCondition;

    explicit WorkerThread(QObject *parent = Q_NULLPTR) : QThread(parent)
    {
        connect(this, &WorkerThread::resultReady, [](const QString &result){qDebug() << result;});
    }

    ~WorkerThread()
    {
        quit();
        wait();
    }

    void run() Q_DECL_OVERRIDE
    {
        forever {
            QMutexLocker locker(&mutex);
            qDebug() << "WorkerThread::run() func, after lock call";
            if (!waitCondition.wait(&mutex, waitPeriod))
                continue;
            else
                emit resultReady("--- wait_cnd is true, WorkerThread::run() func, after wait call");
        }
    }

signals:
    void resultReady(const QString &s);
};

class CoreApplication : public QCoreApplication
{
    Q_OBJECT

    WorkerThread workerThread;

public:
    explicit CoreApplication(int argc, char *argv[]) : QCoreApplication(argc, argv)
    {
        workerThread.start();
    }

public slots:
    void wakeWorkerThread()
    {
        workerThread.waitCondition.wakeOne();
    }
};

int main(int argc, char *argv[])
{
    CoreApplication coreApplication(argc, argv);
    QTimer timer;
    QObject::connect(&timer, &QTimer::timeout, &coreApplication, &CoreApplication::wakeWorkerThread);
    timer.start(1000);
    return coreApplication.exec();
}

#include "main.moc"
Re[2]: Qt5 Qthread
От: milkpot Россия  
Дата: 10.04.19 16:22
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Здравствуйте, milkpot, Вы писали:


M>>Здравствуйте, есть проект на Qt5.6.2 mingw-версии под WinXp, использующий нити Qt. Отладочная версия компилируется и работает.

M>>Релиз версия аварийно завершается при попытке запуска дочерней нити.
M>>...
M>>Приложение аварийно завершается после выполнения функции button9Clicked().

SaZ>createdObj где создаётся? Попробуйте все переменные инициализировать в конструкторе. А лучше даже сразу при объявлении. Но если по существу, то тут нет телепатов — давайте нормальный пример кода, который можно скомпилировать и запустить. Желательно средствами cmake под любую платформу.


Спасибо за ответ. После правки ошибка не проявляется.
Прикрепляю проект в QtCreator'е
http://files.rsdn.org/37906/untitled24.zip

Код с исправлениями.
#ifndef WORKER2_H
#define WORKER2_H

#include "mainwindow.h"
#include <QtCore>
#include <QtGlobal>
#include <QThread>
#include <QMutex>
//#include <QMutexLocker>
#include <QWaitCondition>


//class CreatedObject;

class WorkerThread : public QThread
{
    Q_OBJECT

    bool wait_cnd;
    bool lock_cnd;
    unsigned long one_and_a_half_hour_wait=5400000;

    //explicit WorkerThread( );
    //~QThread();
public:
   // class CreatedObject *cObject;
    /*static*/ QMutex mutex;
/*static*/ QWaitCondition wtc_worker2;

    explicit WorkerThread(QObject *parent = Q_NULLPTR) : QThread(parent)
    {
        //connect(this,)
    }
    ~WorkerThread()
    {
        quit();
        wait();
    }

    void initInnerObjects(/*const CreatedObject *cObjectsPtr*/)
    {
        //cObject=const_cast<CreatedObject *>(cObjectsPtr);
        wait_cnd=false;
        lock_cnd=false;
    }
    //explicit WorkerThread(QObject *parent = Q_NULLPTR){}
    void run() Q_DECL_OVERRIDE {
        QString result;
       // initInnerObjects();
        forever {
//           MutexLocker locker(&mutex);
            mutex.lock();

            qDebug() << "--- Worker: run() func, after lock call";
            wait_cnd=wtc_worker2.wait(&mutex,/*5000*/one_and_a_half_hour_wait);
            if(false==wait_cnd)
            {
                mutex.unlock();
                continue;
               // result=QString(tr("*** wait_cnd is false"));// means the resource may be acquared
               // do_send_result(result);
            }
            else if(true==wait_cnd)
            {
                result=QString(tr("--- wait_cnd is true"));
                do_send_result(result);
            }
            qDebug() << "--- wait_cnd is " << wait_cnd;
            qDebug() << "--- Worker: run() func, after wait call";
           // result=QString(tr(" --- run Worker class |%1|")).arg(result/*parameter*/);
            mutex.unlock();
           // qDebug() << "--- Worker: run() func, after unlock call";
        }
    }
   // Q_SIGNAL void resultReady(const QString &s);
public /*slots*/:
    void launch_threadfunc()
    {
        wtc_worker2.wakeOne();
    }
signals:
    void resultReady(const QString &s);


private slots:
    void do_send_result(const QString &info_msg)
    {
        emit resultReady(info_msg);
    }
};



class CreatedObject : public QObject
{
    Q_OBJECT

    WorkerThread workerThread;
public:
   // /*static*/ QWaitCondition wtc2;

    ~CreatedObject(){
        workerThread.quit();
        workerThread.wait();
    }
    CreatedObject(MainWindow *window/*QObject *parent*/) //: QObject(parent)
    {
        connect(&workerThread, &WorkerThread::resultReady, window,&MainWindow::appendtoLogListBox);
        connect(&workerThread, &WorkerThread::finished, &workerThread, &QObject::deleteLater);
    }

    void initCreatedObject(/*MainWindow *window*/)
    {
//            connect(&workerThread, &WorkerThread::resultReady, window,&MainWindow::appendtoLogListBox);
//            connect(&workerThread, &WorkerThread::finished, &workerThread, &QObject::deleteLater);
            workerThread.initInnerObjects();
            workerThread.start();
    }
   // void do_start()
   // {
   //  //   cObject=new CreatedObject()
   //     workerThread->start();
   // }
    void wf_wake()
    {
        workerThread.launch_threadfunc();// wtc_worker2.wakeOne();
    }

};

#endif // WORKER2_H
Отредактировано 10.04.2019 16:30 milkpot . Предыдущая версия .
Re[3]: Qt5 Qthread
От: Igore Россия  
Дата: 11.04.19 07:55
Оценка:
Здравствуйте, milkpot, Вы писали:

M>Спасибо за ответ. После правки ошибка не проявляется.

M>Прикрепляю проект в QtCreator'е
M>http://files.rsdn.org/37906/untitled24.zip

M>Код с исправлениями.

M>
M>class WorkerThread : public QThread{}

M>class CreatedObject : public QObject
M>{
M>    Q_OBJECT

M>    WorkerThread workerThread;

M>    CreatedObject(MainWindow *window/*QObject *parent*/) //: QObject(parent)
M>    {
M>        connect(&workerThread, &WorkerThread::finished, &workerThread, &QObject::deleteLater);
M>

Как workerThread должен удалиться?
Re[4]: Qt5 Qthread
От: milkpot Россия  
Дата: 11.04.19 11:12
Оценка:
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, milkpot, Вы писали:


M>>Спасибо за ответ. После правки ошибка не проявляется.

M>>Прикрепляю проект в QtCreator'е
M>>http://files.rsdn.org/37906/untitled24.zip

M>>Код с исправлениями.

M>>
M>>class WorkerThread : public QThread{}

M>>class CreatedObject : public QObject
M>>{
M>>    Q_OBJECT

M>>    WorkerThread workerThread;

M>>    CreatedObject(MainWindow *window/*QObject *parent*/) //: QObject(parent)
M>>    {
M>>        connect(&workerThread, &WorkerThread::finished, &workerThread, &QObject::deleteLater);
M>>

I>Как workerThread должен удалиться?

Здравствуйте, вот что приходит в голову.
connect(&workerThread, &WorkerThread::finished, this /*&workerThread*/, &QObject::deleteLater);
Re[5]: Qt5 Qthread
От: K13 http://akvis.com
Дата: 18.04.19 08:24
Оценка:
I>>Как workerThread должен удалиться?

M>Здравствуйте, вот что приходит в голову.

M>
M>connect(&workerThread, &WorkerThread::finished, this /*&workerThread*/, &QObject::deleteLater);
M>


Ню-ню. Вызывать deleteLater(), не зная, на стеке или в куче (ли как мембер другого класса!) размещен объект -- верной дорогой идете, товарищи.
Re[6]: Qt5 Qthread
От: Igore Россия  
Дата: 19.04.19 07:18
Оценка: +1
Здравствуйте, K13, Вы писали:

I>>>Как workerThread должен удалиться?


M>>Здравствуйте, вот что приходит в голову.

M>>
M>>connect(&workerThread, &WorkerThread::finished, this /*&workerThread*/, &QObject::deleteLater);
M>>


K13>Ню-ню. Вызывать deleteLater(), не зная, на стеке или в куче (ли как мембер другого класса!) размещен объект -- верной дорогой идете, товарищи.


Это его код, он должен это знать
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.