C++11 thread in qt 5 - c++

//MainWindow.cpp
void MainWindow::threadedFunction()
{
myDialog = new MyDialogs(list,processList,this);
myDialog->show();
}
void MainWindow::createNewDialog()
{
getProcesses();
//threadedFunction(); //This works fine.
std::thread tx = std::thread(&MainWindow::threadedFunction,this);
tx.join();
}
//MyDialog.cpp
MyDialogs::MyDialogs(QList<int> lists,QStringList list,QObject *parent):QDialog(0)
{
QVBoxLayout *toplay = new QVBoxLayout(this);
listWidget = new QListWidget(this);
x<<list;
l<<lists;
listWidget->addItems(x);
toplay->addWidget(listWidget);
connect(listWidget,SIGNAL(doubleClicked(QModelIndex)),
this,SLOT(getProcessString(QModelIndex)));
}
void MyDialogs::getProcessString(QModelIndex index)
{
selectedProcessString = index.data().toString();
rowIndex = index.row();
}
Already set in pro file.
CONFIG += c++11
when I call threadedFunction directly the code works fine.
But the above mentioned code gives me runtime error.
If I use only qDebug statements in threadedFunction and remove myDialog code, the code runs fine even with the threads. What is the problem? I am using Qt5 with MingW 4.9.1 32bit. And I do not have visual studio installed.

The problem is that you're trying to create a UI object outside the GUI thread. I'm assuming your main function instantiates a QApplication object which starts your event loop. This thread is your one and only GUI thread. I'm guessing your GUI thread is the thread which is creating the thread that is trying instantiate the QListWidget.
If my assumptions are correct then you need to create the QListWidget in the main/GUI thread and then call your thread function. I can't say what you should do in your thread function since I'm not sure what you want to do but there are multiple ways to handle it.
You may want to look at QThread. That class will allow you to use signals and slots, which may make things easier for you. You can use traditional threading constructs (e.g., mutex , wait conditions, etc.) and shared state. There are also ways to post events which go through the message loop (i.e. get sent back into the main/GUI thread).

Related

QT Creator : Program crashes in debug mode but working in Release mode and in DEBUG Mode with breakpoints for QThread based program

I am working on a Desktop (Windows 7) based application and using Qt Creator v 5.6.0 for development of the Program.
I have a very strange issue i.e.
My Program crashes in DEBUG mode but works fine in RELEASE mode.
If in DEBUG mode, and I put break points to find the reason of the crash, then it doesn't crash: It work properly. But if I do not put any break points then it crashes at below code:
Project Background:
My Project includes functionality to read from the device connected at System communication port and transmits data to the MainWindow UI to display. Since to communicate with the communication port we have to use the third party library so I am not using QtSerial Port class which is much simpler and easy to use.
Code Design:
Class MainClass : In this class we have created some forms to display the data read from the device.
Class TestClass: This class will handle all the communication with the device connected at the system Serial Port and use the third party library. This class also have the while loop to read data from the device connected at Serial Port.
Since Test Class is using while loop. So we decided to make a Test Class run in different Thread.
Code for creating Thread in MainClass Constructor:
MainClass::MainClass (QWidget *parent) : QDialog(parent),
ui(new Ui::Analzyer)
{
............................
............................
workerThread = new QThread;
testClassObject = new TestClass(); // Declared in HeaderFile of MainClass
if((workerThread != NULL) && (testClassObject != NULL))
{
workerThread ->moveToThread(testClassObject );
connect(workerThread , SIGNAL(started()), testClassObject, SLOT(SomeFunc()));
connect(testClassObject, SIGNAL(exit()), workerThread , SLOT(quit()));
connect(testClassObject, SIGNAL(exit()), testClassObject, SLOT(deleteLater()));
connect(workerThread , SIGNAL(finished()), workerThread , SLOT(deleteLater()));
// connectToPort Signal is emitted when User clicks the pushbutton from // Main class UI
connect(this, SIGNAL(connectToPort(QString)), testClassObject, SLOT(openPort(QString)));
}
}
Crash Code:
void TestClass::openPort(const QString portName)
{
// Here portName is say : "Appliance Interface v2"
quint32 param2 = getParam2ForPortName(portName);
qint16 portNumber = 0;
QByteArray portNameByteArray = portName.toLatin1();
const char *portNameToOpen = portNameByteArray.data();
// Program crashed when return from this function
if(func1(portNameToOpen , param2, 10 , &portNumber) == true)
{
......................
......................
}
}
Here, I added some qDebug() and found that my code crashes when it returns from or call the func1() which is getting called in slot OpenPort(). Below is the prototype of the func1()
bool func1 (const char portDescription[], uInt32 param2,
uInt16 length, Int16 * portNr);
Since, func1() is the part of the library code. So I can not check the defination of the function func1(). I can assure that there is no problem in func1() Since it is being used in different java based projects and it works.
I did some more debugging on the Project and noticed that when in Run in DEBUG Mode with BreakPoints than in the QT Thread Debug Window I can see my connected Slot but when I do not put any breakPoint than my code crashes and in Qt Thread Debug Window I can not see my connected Slot
So, It looks the problem of connection between the Main Class and the Test Class for openPort Slot.
But I am not able to understand taht when i put breakpoints in operPort() function than I can see my openPort Slot in Qt Thread Debug window but when no breakpoints than openPort Slot is not visible in Qt Thread Debug Window and Program Crashes.
Kindly Suggest,
I can assure that there is no problem in func1() Since it is being used in different java based projects and it works.
Wait, is func1() C++ or Java ?
Also, how can you be sure it works ?
Get the library source, compile it yourself, and debug in it.
And, just to be sure, check values of your variables while debugging, and qDebug() them when not debugging
I apologise for replying on my own post but after lots of dicussion on StackOverflow and google. I was able to solve the Issue.
To Solve the Issue:
I changed the SLOT(openPort) as mentioned below:
Connect(this, SIGNAL(connectToPort(QString)), testClassObject, SLOT(openPort(QString)), Qt::DirectConnection);
That is to use the "Qt:DirectConnection" method. If we don't specify a connection method, the direct method is automatically used for connections between objects on the SAME thread.
Since here we have created a new QThread for TestClass and using a thirdParty library which might not be a thread safe.
So using "Qt::DirectConnection" make the openPort() SlOT to run in MainClass Thread. Basically, it's as if emitting the signal calls the slot method "directly".

Read a file in background to update Qjsonvalue

I need to update the content of a field on my QWidget via a JSON file (updated in real time). I've read about functions readLine() and readAll() of QFile, but when I try a loop like :
while(true):
jsfile.readLine()
creation of objects, update of values, display etc ...
I lost the focus on my window. But I want to keep the control of the application with my buttons and obviously to watch the evolution of the JSON values.
I have thought that Qt manages itself the events and keeps the focus on the current window, but like I've said, it's not the case.
Is there a good solution (multi threads maybe) to use my window while the application reads the file (with new informations in real time)?
(With the constraint "real time" I can't read the whole file every time and I've no choice about the format of this file)
Update
I tried the thread method.
So, I choose to create my thread instance into the main (with my main window) and connect here. But, when I run the program, I've this error :
no matching member function for call to 'connect'
Reader reader;
QObject::connect(controler, SIGNAL(ready()),
reader, SLOT(received()));
According to this error, I've thought that the reason was main don't inherits of Object, and so, I've move the connection ans the creation of thread instance into my main window.
Reader reader;
QObject::connect(reader, SIGNAL(newobject(QJsonObject)),
this, SLOT(displayJSON(QJsonObject)));
With this one, I've the same error while I've already connect lot of widget into this class without any error.
What can be the problem ?
Update 2
I've a solution when I give as argument my main window (controler) in reader's constructor and connect into this one but, if possible, I would an explanation for the previous problem.
The current problem that I have is that signals are emit well but slots are executed after the end the application (so after the end of the thread's execution and not during)
This isn't really the subject of this topic so we can close this one.
You can use QThread (Qt documentation: QThread) class to create a thread, which will read your file. The main thread will execute your GUI application and it will be available during file reading.
You can find a simple example in documentation for creating your thread:
class WorkerThread : public QThread
{
Q_OBJECT
void run() Q_DECL_OVERRIDE {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &s);
};
void MyObject::startWorkInAThread()
{
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
You can modify this example for your purpose. For example, WorkerThread for your task may be something like this:
class WorkerThread : public QThread
{
Q_OBJECT
void run() Q_DECL_OVERRIDE {
while(!stopFlag)
{
// read JSON file to QByteArray. Use QFile and QTextStream
// use QJsonDocument to read JSON content
// find what is new in JSON
emit signalSomethingNew(/*parameters*/);
QThread::currentThread()->msleep(/*timeout*/);
}
}
signals:
void signalSomethingNew(/*parameters*/);
};
At the end you must implement slot on your QWidget for signalSomethingNew(/*parameters*/) and make connection:
connect(yourThread, &WorkingThread::signalSomethingNew, youWidget, &YouWidget::yourSlot);
For working with JSON data: QJsonDocument
I'm interpreting your question as "my application is unresponsive whilst doing work" rather than "my focus jumped to another window" - please comment if you meant something different.
You have a choice of options:
Create and run a background QThread to do the work. Have it emit signals (connected to your widgets using Qt::QueuedConnection - the default) when it has results to display.
This is a good solution when the worker has a lot of computation to do, or needs all the input to be read before it can start. It works very well when the target system has processors available with no other work to do.
Use a QSocketNotifier to signal your GUI thread when some of the input becomes available (note that the name is misleading - it actually works on all kinds of file descriptor, not just sockets).
This is appropriate when the algorithm is simple and incremental - i.e. if a small chunk of input can be read and processed quickly.
Incorporate periodic calls to processEvents() in your algorithm:
auto *const dispatcher = QThread::currentThread()->eventDispatcher;
while (line = json.readLine()) {
doSomethingWith(line);
if (dispatcher)
dispatcher->processEvents();
}
This won't work unless you can modify the algorithm like this - if the loop is in somebody else's (closed) code, then you'll need one of the other solutions.

QThread, creating GUI widget element on a thread

I've been trying that for a while and seems it's not something common as I didn't find much information about.
I have a QTree in which I put item, on my Item i have a check box on the first column.
Problem: Checkbox is not optimised to be treated as so and takes quite some time as soon as there is several elements.
So i'm using a thread to create the checkbox before putting in my list, but seems impossible to get the checkbox back on the GUI thread.
void CheckItemThread::run()
{
setPriority(QThread::IdlePriority);
QCheckBox *m_check;
m_check = new QCheckBox();
emit done(m_check);
}
My main thread:
myCheckItem::myCheckItem(QTreeWidget *parent, QStringList columnNames ):
myWidgetItem(parent)
{
m_parent = parent;
m_columnNames = columnNames;
connect(&TheThread,SIGNAL(done(QCheckBox *)), this, SLOT(retThread(QCheckBox *)));
connect(&TheThread,SIGNAL(terminated()), this, SLOT(endThread()));
TheThread.setdata(columnNames,parent, this);
TheThread.start(); //run thread
}
void myCheckItem::endThread()
{
m_check->setParent(m_parent);
connect(m_check, SIGNAL(stateChanged(int)), this, SLOT(onCheckBox(int)));
}
void myCheckItem::retThread(QCheckBox *check)
{
m_check = check;
}
Maybe I'm missing something or it's simple not possible to reattach the thread ?
Thanks
You must not create, edit or work with UI elements in other threads. UI elements must be worked with in the main thread (UI thread). If you have time-consuming prerequisites before "drawing" a checkbox, do your work in a thread (eventually QtConcurrent) and send a signal to the main thread for creating the corresponding checkbox.
You can change GUI elements only in main thread. How many checkboxes do you have? Maybe you should create a limited count of checkboxes and reuse them when needed?

Qt - updating main window with second thread

i have an multithreaded qt application. when i am doing some processes in mainwindow.cpp, at the same time, i want to update mainwindow.ui from other thread.
i have mythread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include "mainwindow.h"
class mythread : public QThread
{
public:
void run();
mythread( MainWindow* ana );
MainWindow* ana;
private:
};
#endif // MYTHREAD_H
mythread.cpp
mythread::mythread(MainWindow* a)
{
cout << "thread created" << endl;
ana = a;
}
void mythread::run()
{
QPixmap i1 (":/notes/pic/4mdodiyez.jpg");
QLabel *label = new QLabel();
label->setPixmap(i1);
ana->ui->horizontalLayout_4->addWidget(label);
}
but the problem is that, i cannot reach the ana->ui->horizontalLayout_4->addWidget(label);
how can i do that?
but the problem is that, i cannot reach the
ana->ui->horizontalLayout_4->addWidget(label);
Put your UI modifications in a slot in your main window, and connect a thread signal to that slot, chances are it will work. I think only the main thread has access to the UI in Qt. Thus if you want GUI functionality, it must be there, and can be only signaled from other threads.
OK, here is a simple example. BTW, your scenario doesn't really require to extend QThread - so you are better off not doing it, unless you really have to. That is why in this example I will use a normal QThread with a QObject based worker instead, but the concept is the same if you subclass QThread:
The main UI:
class MainUI : public QWidget
{
Q_OBJECT
public:
explicit MainUI(QWidget *parent = 0): QWidget(parent) {
layout = new QHBoxLayout(this);
setLayout(layout);
QThread *thread = new QThread(this);
GUIUpdater *updater = new GUIUpdater();
updater->moveToThread(thread);
connect(updater, SIGNAL(requestNewLabel(QString)), this, SLOT(createLabel(QString)));
connect(thread, SIGNAL(destroyed()), updater, SLOT(deleteLater()));
updater->newLabel("h:/test.png");
}
public slots:
void createLabel(const QString &imgSource) {
QPixmap i1(imgSource);
QLabel *label = new QLabel(this);
label->setPixmap(i1);
layout->addWidget(label);
}
private:
QHBoxLayout *layout;
};
... and the worker object:
class GUIUpdater : public QObject {
Q_OBJECT
public:
explicit GUIUpdater(QObject *parent = 0) : QObject(parent) {}
void newLabel(const QString &image) { emit requestNewLabel(image); }
signals:
void requestNewLabel(const QString &);
};
The worker object is created and moved to another thread, then connected to the slot that creates the labels, then its newLabel method is invoked, which is just a wrapper to emit the requestNewLabel signal and pass the path to the image. The signal is then passed from the worker object/thread to the main UI slot along with the image path parameter and a new label is added to the layout.
Since the worker object is created without parent in order to be able to move it to another thread, we also connect the thread destroyed signal to the worker deleteLater() slot.
First and foremost, "you're doing it wrong". Normally you want to create a class derived from a QObject and move that class to a new thread object instead of deriving your class from a Qthread
Now to get onto the specifics of your question, you're not able to directly modify the ui elements of your main GUI thread from a separate thread. You have to connect a signal from your 2nd thread to a slot in your main thread. You can pass any data that you need through this signal/slot connection but you're unable to directly modify the ui element (which in all honestly you probably do not want to if you intend to keep the frontend of your app separate from the backend). Checkout Qt's signal and slot documentation for a whole lot more information
how can i do that?
You've already got the answers to what you should be doing, but not a why, so I'm going to add a why.
The reason you don't modify GUI elements from another thread is because GUI elements are usually not thread-safe. This means that if both your main GUI thread and your worker thread update the UI, you cannot be certain of the order of what happened when.
For reading data generally this can sometimes be fine (e.g. checking a condition) but generally you do not want this to be case. For writing data, this is almost always the source of very, very stressful bugs which occur "at random".
Another answer has remarked on good design principles - not only does constraining your GUI logic to one thread and firing signals to talk to it get rid of your race condition issues, but it also forces you to compartmentalize your code nicely. Presentation logic (the display bit) and data processing logic can then be cleanly separated out, which makes maintaining the two much easier.
At this stage you might think: heck, this threads business is farrrrrr too much work! I'll just avoid that. To see why this is a bad idea, implement a file copy program in a single thread with a simple progress bar telling you how far along the copy is. Run it on a large file. On Windows, after a while, the application will "go white" (or on XP I think it goes gray) and will be "not responding". This is very literally what is happening.
GUI applications internally mostly work on the variation of "one big loop" processing and dispatching messages. Windows, for example, measures response time to those messages. If a message takes too long to get a response, Windows then decides it is dead, and takes over. This is documented in GetMessage().
So whilst it may seem like quite a bit of work, Signals/Slots (an event-driven model) is basically the way to go - another way to think of this is that it is totally acceptable for your threads to generate "events" for the UI too - such as progress updates and the like.

qt signals/slots in a plugin

I have an app with such structure: all the datatypes (class INode) are stored in plugins (DLLs). Some of the datatypes can be drawn (if they're IDrawable).
To load an object of, e.g. class PointCloudNode: public INode I have a special input plugin (DLL) which is called class PointCloudParser: public IIOPlugin and IIOPlugin is a thread with some specific functionality: class IIOPlugin: public QThread.
All the objects are created by NodeFactory class which is a singleton stored in separate DLL.
And here's the problem:
void PointCloudNode::update()
{
QObject::connect (this,SIGNAL(tmptmp()),this,SLOT(drawObject()));
emit tmptmp();
}
If I do this from any thread (main thread or the Input Plugin thread)
NodeFactory* fab = NodeFactory::getInstance();
boost::shared_ptr<INode> pc(fab->createNode("pointCloud","myPC"));
boost::shared_ptr<IDrawable> dr = boost::dynamic_pointer_cast<IDrawable>(pc);
dr->update();
The update launches, the tmptmp() signal is emitted, and the slot (drawObject()) executes correctly.
BUT
if do just the same, but create the object in my Input Plugin, pass over the shared pointer and execute dr->update() in another function, the slot drawObject() is never entered though all the code is executed (including connect, etc.).
To be more precise, here's the Input Plugin:
void PointCloudParserPlugin::doLoad(const QString& inputName, boost::shared_ptr<INode> container)
{
NodeFactory* factory = NodeFactory::getInstance();
boost::shared_ptr<INode> node = factory->createNode("pointCloud", inputName);
// here goes the loading itself, nothing special...
container->addChild(node); //that's the container where I keep all the objects
//boost::dynamic_pointer_cast<IDrawable>(container->getChild(inputName))->update();
//If I uncomment this line, it all works: the slot is launched.
emit loadingFinished(inputName); // it executes the following function
}
The last emit is connected to this:
void GeomBox::updateVisualization(const QString& fileName)
{
boost::shared_ptr<INode> node = container_->getChild(fileName);
boost::shared_ptr<IDrawable> nodeDrawable = boost::dynamic_pointer_cast<IDrawable>(node);
nodeDrawable->update(); //this is the problem line: update() executes, connect() works, but the slot never runs :(
}
How come? The node object is the same all the way through, it is valid. Every line in code in launched, QObject::connect doesn't write anything to debug window, the signal tmptmp() is emitted, but the slot drawObject() in one case is never reached? Any ideas?
Upd.: If I do not inherit IIOPlugin from QThread, everything works fine (i.e. load the object in the main thread). I expected the signals/slots to work across the threads...
Since you are sending a signal across to a different thread, you might need to explicitly tell Qt that the connection should be a queued one:
QObject::connect(this, SIGNAL(tmptmp()), this, SLOT(drawObject()), Qt::QueuedConnection );
By default Qt will use Qt::AutoConnection as that last parameter, and it will choose whether to use a direct connection (if the slot is in the same thread as the emitter) or a queued connection (if the slot is in a different thread). But since your thread is in a separate library, maybe Qt isn't making the right assumption here.