От:
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().
От:
SaZ
Дата: 09.04.19 19:43
Оценка:
2 (1)
Здравствуйте, milkpot, Вы писали:
M>Здравствуйте, есть проект на Qt5.6.2 mingw-версии под WinXp, использующий нити Qt. Отладочная версия компилируется и работает.
M>Релиз версия аварийно завершается при попытке запуска дочерней нити.
M>...
M>Приложение аварийно завершается после выполнения функции button9Clicked().
createdObj где создаётся? Попробуйте все переменные инициализировать в конструкторе. А лучше даже сразу при объявлении. Но если по существу, то тут нет телепатов — давайте нормальный пример кода, который можно скомпилировать и запустить. Желательно средствами cmake под любую платформу.
От:
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();
}
}
Здравствуйте, 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"
От:
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
От:
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 должен удалиться?
От:
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);
I>>Как workerThread должен удалиться?
M>Здравствуйте, вот что приходит в голову.
M>M>connect(&workerThread, &WorkerThread::finished, this /*&workerThread*/ , &QObject::deleteLater);
M>
Ню-ню. Вызывать deleteLater(), не зная, на стеке или в куче (ли как мембер другого класса!) размещен объект -- верной дорогой идете, товарищи.
От:
Igore
Дата: 19.04.19 07:18
Оценка:
+1
Здравствуйте, K13, Вы писали:
I>>>Как workerThread должен удалиться?
M>>Здравствуйте, вот что приходит в голову.
M>>M>>connect(&workerThread, &WorkerThread::finished, this /*&workerThread*/ , &QObject::deleteLater);
M>>
K13>Ню-ню. Вызывать deleteLater(), не зная, на стеке или в куче (ли как мембер другого класса!) размещен объект -- верной дорогой идете, товарищи.
Это его код, он должен это знать
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить