why this application crashes on new thread starts, please somybody point out me have i done enything wrong..
newthread.h
#ifndef NEWTHREAD_H
#define NEWTHREAD_H
#include <QThread>
class newthread: public QThread
{
public:
newthread();
public slots:
void run();
};
#endif // NEWTHREAD_H
newthread.cpp
#include "newthread.h"
#include "mainwindow.h"
#include<QDebug>
newthread::newthread()
{
}
void newthread::run(){
qDebug()<<"thread executed";
}
mainwindow.cpp
#include <QtGui>
#include "mainwindow.h"
#include"newthread.h"
MainWindow::MainWindow(QWidget *parent)
{
setupUi(this);
connect(pushButton,SIGNAL(clicked()),this, SLOT(opthread()));
}
void MainWindow::opthread(){
newthread th;
th.start();
}
here in the main window there is a public slot called ophthread(). as shown above when a button in the main window is pressed that slot will trig. in it i i declared a newthread object called th and th.start() to start it. have i done enything wrong.
this compilles without errors. but when run the binary it gives a error and crashes.
my second question is if i need the thread to write some text on a textEdit in the main window how to do that. is it possible newthread class access objects in the mainwindow class.
void MainWindow::opthread(){
newthread th;
th.start();
}
You are creating the thread object on the stack. He will be destroyed when the function opthread returns. And from the Qt documentation :
Deleting a running QThread (i.e. isFinished() returns false) will
probably result in a program crash. Wait for the finished() signal
before deleting the QThread.
You need to provide a greater lifespan for your newthread object. waiting for it to be finished is not an option, as it will result in a sequential execution. Either you use class members or you allocate your thread objects on the heap.
Personal opinion:
Not only sub-classing QThread is not the most appropriate method of getting it done, I believe you don't need a thread at all.
As you're creating the thread with: -
newthread th;
It will then go out of scope and get deleted, which is not what you're wanting.
You need to dynamically create the object: -
newthread* th = new newthread;
Related
I am working on a data logger in QT framework. I Intend to save log strings to files and print to the console in a separate watcher thread. In that separate thread I need to watch my QStringList for new items added. If there are new items I deque them and log. I was wondering what is the mechanism used for this in Qt framework. In STD lib i used condition_variable for this task like this:
/*!
* \brief puts a \ref logline_t object at the end of the queue
* #param s object to be added to queue
*/
void CLogger::push_back(logline_t* s)
{
unique_lock<mutex> ul(m_mutex2);
s->queSize = m_data.size();
m_data.emplace_back(move(s));
m_cv.notify_all();
}
/*!
* \brief takes a \ref logline_t object from the beggining of the queue
* #return first \ref logline_t object
*/
CLogger::logline_t CLogger::pop_front()
{
unique_lock<mutex> ul(m_mutex2);
m_cv.wait(ul, [this]() { return !m_data.empty(); });
assert(m_data.front());
logline_t retVal = move(*m_data.front());
delete m_data.front();
m_data.front() = NULL;
m_data.pop_front();
return retVal;
}
m_cv is the conditional variable object. How can this functionality be acquired with QT? I bet there is a lot better way :). I would appreciate all help.
Ps: I know pointer functions parameters are not asserted, this is an old code... :P
There are a couple of ways of doing the notification in Qt.
Signals and Slots
Signals and slots can be sent between threads, when making the connection, you set the connection type to Qt::QueuedConnection or Qt::BlockingQueuedConnection.
You may want to create a wrapper class around the QStringList so that modifications can trigger the signals that other classes listen for.
QMutex and QWaitCondition
You can use the Qt thread synchronisation classes QMutex and QWaitCondition to do the classic manual synchronisation like you have done previously. When using QMutex, the QMutexLocker is useful for scope lock and release of a QMutex.
Here's an example of doing this signals and slots. You may want to do your own benchmarks to test whether this fits your needs. Please also note that while signals and slots guarantee thread-safety, they don't guarantee that the messages will appear in the same order they were sent. That being said, I've used this mechanism for years and it has yet to happen for me.
First, create a couple of classes:
Loggee
// loggee.hpp
#ifndef LOGGEE_HPP
#define LOGGEE_HPP
#include <QObject>
class Loggee : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
void someEventHappened(int id);
signals:
void newLogLineNotify(QString const&);
};
#endif // LOGGEE_HPP
and the .cpp file:
#include "loggee.hpp"
void Loggee::someEventHappened(int id)
{
auto toLog = QString::number(id);
emit newLogLineNotify(toLog);
}
Logger
#ifndef LOGGER_HPP
#define LOGGER_HPP
#include <QObject>
class Logger : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
signals:
public slots:
void onLogEventHappened(QString const&);
};
#endif // LOGGER_HPP
and the .cpp file:
#include <QDebug>
#include <QThread>
#include "logger.hpp"
void Logger::onLogEventHappened(QString const& str)
{
qDebug() << QThread::currentThreadId() << str;
}
the rest
#include <QDebug>
#include <QThread>
#include <QCoreApplication>
#include <QTimer>
#include "logger.hpp"
#include "loggee.hpp"
int main(int argc, char** argv)
{
QCoreApplication a(argc, argv);
QThread t;
t.start();
Logger foo;
Loggee bar;
foo.moveToThread(&t);
QObject::connect(&bar, &Loggee::newLogLineNotify,
&foo, &Logger::onLogEventHappened,
Qt::AutoConnection);
qDebug() << "Current thread id: " << QThread::currentThreadId();
bar.someEventHappened(42);
QTimer::singleShot(3000, [&]{ bar.someEventHappened(43); });
return a.exec();
}
In this demo, I create a QThread and a Logger, move handling of this new Logger's slots to this new thread's event loop. Then I connect Loggee's signal with Logger's slot using Qt::AutoConnection. This is the default but I stated it explicitly to show that you can change this (i.e. to Qt::QueuedConnection which would queue the execution of the slot even if both threads lived in the same thread).
Then I cause the Loggee to emit¹ a singal. It gets properly scheduled and causes the logging slot to be executed in the receiver's thread.
¹ emit is #define emit /*null*/, so you can omit it if you want
If you are just looking for the Qt equivalents to the classes you have been using:
std::mutex -> QMutex
std::condition_variable -> QWaitCondition
std::unique_lock -> QMutexLocker
I try to create something like a window pool. You can use these windows everywhere in your program to display graphics and plot diagrams etc. The widgets working well but the main problem at the moment is the frustrated tries, to create the pool. One non QObject-Object should represent a QMainWindow to cut the bindings to Qt.
I cannot create a widget -> I tried invokeMethode, connect and QTimer but nothing works. Sometimes the methods don´t get called or I am not in the gui thread... Any idea?
Edit 2 - new version:
header:
#pragma once
#include <QMainWindow>
#include <QTimer>
class MyWindow : QObject
{
Q_OBJECT
public:
MyWindow();
};
class QWindowPool : public QObject
{
Q_OBJECT
public:
QWindowPool();
public slots:
void createWindow();
};
class QWindow : public QMainWindow
{
Q_OBJECT
};
cpp:
#include
#include <QApplication>
#include <QTimer>
#include <QtConcurrent/qtconcurrentrun.h>
#include <iostream>
#include <future>
static QWindowPool *pool = new QWindowPool();
QWindowPool::QWindowPool() {
// check if app is running
if (!QApplication::instance()) {
bool appOnline = false;
QtConcurrent::run([&appOnline](){
int c = 0;
new QApplication(c, NULL);
appOnline = true;
qApp->exec();
});
while (!appOnline) {}
}
moveToThread(QApplication::instance()->thread());
}
void QWindowPool::createWindow() {
printf("window created\n");
new QWindow();
}
MyWindow::MyWindow() {
QTimer::singleShot(0, pool, SLOT(createWindow()));
}
int main()
{
MyWindow mw;
std::thread t1([](){
MyWindow mw;
std::thread t2([](){
MyWindow mw;
});
t2.join();
});
t1.join();
std::cin.ignore();
return 0;
}
Now the code do what is should. I can create widgets in different threads. But there are two scenarios, where I would stack at:
Someone (anyone who would like to use this library) creates before me QApplication and never calls qApp->exec
Someone want to create an own UI with Widget but does not work in my qt::concurrent gui thread. He would probably not get along with this.
What I want is in the final application:
The user should get the possibility to write anywhere in his code and in any thread:
MyWindow mw(dataToDisplay)
and the window should be created and showed to him.
Qt will only let you create widgets from the main GUI thread, this is explicitly mentioned in the docs (emphasis mine):
As mentioned, each program has one thread when it is started. This
thread is called the "main thread" (also known as the "GUI thread" in
Qt applications). The Qt GUI must run in this thread. All widgets and
several related classes, for example QPixmap, don't work in secondary
threads. A secondary thread is commonly referred to as a "worker
thread" because it is used to offload processing work from the main
thread.
I would like to run a timer inside a QThread. I have written some code in which i am getting some error during the run time. Please guide me into the right direction. What am I doing wrong?
(Parent is QThread(0x1498d10), parent's thread is QThread(0x11272b0), current thread is QThread(0x1498d10)
mainwindow.h //main .h file
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "mythread.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
MyThread *myt;
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp //main .cpp file
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myt=new MyThread();
myt->start();
MainWindow w;
}
MainWindow::~MainWindow()
{
delete ui;
}
mythread.h // class for thread
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QTimer>
class MyThread:public QThread
{
public:
MyThread();
void run();
QTimer *thr;
public slots:
void slo();
};
#endif // MYTHREAD_H
mythread.cpp
#include "mythread.h"
MyThread::MyThread()
{
thr= new QTimer();
connect(thr,SIGNAL(timeout()),this,SLOT(slo()));
}
void MyThread::run()
{
thr->start(1000);
}
void MyThread::slo()
{
int i,j=0;
i=i+j;
}
Just my humble opinion - Do not to subclass QThread anymore, when you do not need to.
I think, you just want to run your class in new thread or more probably you do not want to block other tasks. Your class is not thread itself. Subclassing basically means that your class IS what you are subclassing.
In other words: Let QThread do its job and concentrate on your class to do what it should do.
Example: MyClass itself does not know anything about threads. It just do what it has to do. Incrementing value and showing results ( plus some sleep part to show how it can block other functions or gui )
Header file
#include <QTimer>
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(bool willSleep, QString name, QObject *parent = 0);
public slots:
void updateCount();
private:
QTimer *timer;
int count;
bool m_wantToSleep;
};
Implementation
#include "myclass.h"
#include <QDebug>
MyClass::MyClass(bool wantToSleep, QString name, QObject *parent) :
QObject(parent)
{
this->setObjectName(name);
m_wantToSleep = wantToSleep;
count = 0;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateCount()));
timer->start(100);
}
void MyClass::updateCount()
{
++count;
qDebug() << objectName() << " count: " << count;
if (m_wantToSleep)
sleep(1);
}
We have code which does the job.
Now implement more threads - its very simple ( memory management, etc not handled to have simple example )
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThread *thread1 = new QThread; // First thread
QThread *thread2 = new QThread; // Second thread
thread1->start();
thread2->start();
MyClass *myClass = new MyClass(false, "normal class");
MyClass *mySleepClass = new MyClass(true, "sleeper class");
// Better to implement start slot to start timer ( not implemented )
// connect(thread1, SIGNAL(started), myClass, SLOT(start()));
// but this suffice, because timer will emit first signal after class is moved to another thred
//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
}
MainWindow::~MainWindow()
{
delete ui;
}
Now we can play with threads:
Blocking GUI ( of course we do not want this )
Initial example works without using new threads. Objects are in current thread and that's why GUI will be blocked. ( since I use sleep function in one instance )
//mySleepClass->moveToThread(thread1);
//myClass->moveToThread(thread1);
Non blocking GUI
We have two more threads running. Why not to use them. In example QThreads are already running, but they play with nothing. Let's move our instances there, to ensure main loop, where GUI is living will not be blocked anymore.
Magic function is moveToThread
Uncomment lines and you can see, that GUI will not be blocked. Both instances are in new thread. But then again, there is a sleep function so One should be counting faster then other. But it is not. Because they are blocking each other. They are in one thread.
mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread1);
Results in both previous cases should be: ( instances lives in same thread and shares the same event loop, so they are blocking each other )
"normal class" count: 1
"sleeper class" count: 1
"normal class" count: 2
"sleeper class" count: 2
"normal class" count: 3
"sleeper class" count: 3
So move them to separate thread
Now GUI is not blocked, niether instances each other.
mySleepClass->moveToThread(thread1);
myClass->moveToThread(thread2);
Results should be: ( and GUI should not be blocked )
"sleeper class" count: 1
"normal class" count: 1
"normal class" count: 2
"normal class" count: 3
"normal class" count: 4
"normal class" count: 5
Hope It was understandable. As for me, this is more logic aproach then subclassing.
Of course you can create QThread in your MyClass, it is not necessary to create it oustide MyClass, I just wanted to show, that you can create one thread and move there more instances.
For anyone who disagree, I just wanted to say that: MyClass is counter with thread support sounds better then: MyClass is thread with counter ability :)
Your timer does not belong to your thread. You should create it in your run() method or you should call tmer->moveToThread before connecting it to slots, but after thread was started.
Check it: MyThread belongs to your main thread. You create timer in constructor of MyThread - so timer belongs to main thread too. But you are trying to initialize and use it in ::run method, that belongs to other thread.
In order to do this, you need to have event loop in your thread.
From QTimer's man page:
In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI thread, use QThread::exec(). Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
From QThread's man page:
int QThread::exec () [protected]
Enters the event loop and waits until exit() is called, returning the value that was passed to exit(). The value returned is 0 if exit() is called via quit().
It is necessary to call this function to start event handling.
Also, you need to have Q_OBJECT in your class:
class MyThread:public QThread
{
Q_OBJECT
And finally, as Dmitry noted, you need to create QTimer inside your thread, so the entire cpp file should look like this:
#include "mythread.h"
MyThread::MyThread()
{
}
void MyThread::run()
{
thr= new QTimer();
connect(thr,SIGNAL(timeout()),this,SLOT(slo()));
thr->start(1000);
exec();
}
void MyThread::slo()
{
int i = 0,j=0;
i=i+j;
}
Also, read this document.
I was able to create a simple example that starts a timer within another thread, using lambda functions. Here is the code:
#include <QCoreApplication>
#include <QObject>
#include <QTimer>
#include <QThread>
#include <QDebug>
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
QThread* thread = new QThread(&app);
QObject::connect(thread, &QThread::started, [=]()
{
qInfo() << "Thread started";
QTimer* timer1 = new QTimer(thread);
timer1->setInterval(100);
QObject::connect(timer1, &QTimer::timeout, [=]()
{
qInfo() << "Timer1 " << QThread::currentThreadId();
});
timer1->start();
});
thread->start();
QTimer timer2(&app);
QObject::connect(&timer2, &QTimer::timeout, [=]()
{
qInfo() << "Timer2 " << QThread::currentThreadId();
});
timer2.setInterval(100);
timer2.start();
return app.exec();
}
I'm new to StackOverflow and wondering if I'm doing this right:
I'm writing a simple Qt application to test multi-threading (something I am also completely new to). I made a MainWindow that contains widgets, and a class MyThread that subclasses QThread and overrides the run() method.
The application simply displays two buttons, "Start Counter" and "Stop Counter", and a text field. When "start counter" is pressed, a worker thread is created and runs in the background, continuously incrementing a counter in a while loop and signaling the main thread (where the GUI is) with the updated value. When "Stop Counter" is pressed, a signal is sent to the main thread that stops the while loop, and the counter is stopped until "Start Counter" is pressed again.
This works perfectly fine ... but is it the best way? I'm new at this, and read a lot of people saying "don't subclass QThread" and other people saying "subclass QThread", and it's a little bit confusing. If this isn't the best way to implement this sort of thing (run a computationally-intensive loop in a background thread with "start" and "stop" buttons), what is? If I'm doing it wrong, how do I do it right? I don't want to learn the wrong way.
Thank you! And here's the code:
MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QMutex>
class MyThread : public QThread
{
Q_OBJECT
public slots:
void stopRunning();
protected:
virtual void run();
signals:
void signalValueUpdated(QString);
private:
bool isRunning;
};
MyThread.cpp
#include "MyThread.h"
#include <QString>
void MyThread::run()
{
qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
static int value=0; //If this is not static, then it is reset to 0 every time this function is called.
isRunning = 1;
while(isRunning == 1)
{
QString string = QString("value: %1").arg(value++);
sleep(1/1000); //If this isn't here, the counter increments way too fast and dies, or something; the app freezes, anyway.
emit signalValueUpdated(string);
}
}
void MyThread::stopRunning()
{
isRunning = 0;
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QApplication>
#include <QPushButton>
#include <QHBoxLayout>
#include <QLineEdit>
#include "MyThread.h"
class MainWindow : public QWidget
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
private:
//Widgets
QHBoxLayout * boxLayout;
QPushButton * startButton;
QPushButton * stopButton;
QLineEdit * lineEdit;
MyThread thread;
};
#endif
MainWindow.cpp
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
boxLayout = new QHBoxLayout(this);
startButton = new QPushButton("Start Counter", this);
stopButton = new QPushButton("Stop Counter", this);
lineEdit = new QLineEdit(this);
boxLayout->addWidget(startButton);
boxLayout->addWidget(stopButton);
boxLayout->addWidget(lineEdit);
qDebug("Thread id %d",(int)QThread::currentThreadId());
//When the start button is pressed, invoke the start() method in the counter thread
QObject::connect(startButton,SIGNAL(clicked()),&thread,SLOT(start()), Qt::QueuedConnection);
//When the stop button is pressed, invoke the stop() method in the counter thread
QObject::connect(stopButton,SIGNAL(clicked()),&thread,SLOT(stopRunning()), Qt::QueuedConnection);
//When the counter thread emits a signal saying its value has been updated, reflect that change in the lineEdit field.
QObject::connect(&thread,SIGNAL(signalValueUpdated(const QString&)),lineEdit,SLOT(setText(const QString&)), Qt::QueuedConnection);
}
Most of the time QThread sub-classing is a wrong way to do threading in Qt. I suggest you to read an article about threads, event loops and other which could give you an idea how to use threads in Qt in a better way. But do not listen to anyone who arguing that there is the only one right way to use QThread. There are 2 ways and while subclassing is not needed in general it could be useful sometimes. You just need to use non-subclassing way until you really need to subclass. In your particular case you don't need subclassing.
Replace sleep(1/1000); with msleep(100); Things will be just fine :)
NOTE: THE CODE PROVIDED JUST GIVES THE IDEA OF THE STRUCTURE OF THE APPLICATION
I have a Qt application, interfacing with external hardware. The structure is such that the class for interfacing with the hardware inherits from QObject and is composed with the main GUI thread class. Let's say the class is test.h, here is its sample code:
#ifndef TEST_H
#define TEST_H
#include <QLineEdit>
#include <QString>
#include <QTimer>
#include "ui_test.h"
#define TIMEOUT 100
class TestObj;
class TestApp:public QWidget, public Ui::mTestForm
{
Q_OBJECT
public:
TestApp(QWidget* parent=0);
QTimer* mTimer;
bool mWindowClosed;
TestObj* mObj;
public slots:
void UpdateText();
void Exit();
};
class TestObj:public QObject
{
Q_OBJECT
public:
TestObj();
void RandomTest();
};
#endif
Code for test.cpp is
#include "test.h"
TestApp::TestApp(QWidget* parent):QWidget(parent)
{
setupUi(this);
mObj = new TestObj();
mWindowClosed=false;
mLineEdit->setText("Hello");
mTimer=new QTimer();
mTimer->singleShot(1000,this,SLOT(UpdateText()));
connect(mExitButton,SIGNAL(clicked()),this, SLOT(Exit()));
}
void TestApp::UpdateText()
{
if(mWindowClosed)
{
//QApplication::processEvents();
return;
}
else
{
//QApplication::processEvents();
mObj->RandomTest();
mLineEdit->setText("Hi");
mTimer->singleShot(100,this,SLOT(UpdateText()));
}
}
void TestApp::Exit()
{
mWindowClosed=true;
}
Now consider that TestObj class is the one used to interface with the hardware. This class sends three possible commands (in actual code, the above is just a sample structure) with different timeouts to the hardware, thus we have a timer which is used when sending commands (implemented as functions) to the hardware. Each of these has a processEvents entry to identify any changes to variables in the meanwhile.
The problem is this module is responsible for a steady rise in memory during program execution.
When I comment out the UpdateText() function in the TestApp constructor, the app works fine.
My guess is that most likely there is queuing of signal slots due to which the memory increase, because there are lots of GUI events taking place. And since the class isn't implemented as a separate thread and clubbed with the main GUI thread. There is continuous update of the main thread.
Can someone suggest a way out? I don't have the authority to change the design otherwise I would have implemented the interface class as a thread. So if a solution can be suggested with the current design as is, it would be beneficial.
Creating a regular timer, setting its interval to 100 and connecting its timout signal to the
UpdateText function will avoid events piling up.
P.S: You don't need a QTimer object for singleShot, you can call QTimer::singleShot directly.
Wild guess:
Try changing this:
mTimer->singleShot(100,this,SLOT(UpdateText()));
to this:
if (!slotSet)
{
mTimer->singleShot(100,this,SLOT(UpdateText()));
slotSet = true;
}