I'm using the QtSerialPort library to talk to a virtual COM port via USB. The COM port returns data and works properly when testing it with the example projects given with QtSerialPort, but fails when I run it as part of my project.
I inspected the instantiation chain and threads that lead up to the QtSerialPort being instantiated, and found something a little strange. The results are below.
main()
MainWindow (Thread 0xbf8dbe0) // Thread "A"
HardwareManager (Thread 0xbf8dbe0) // Thread "A"
QSerialPort (Thread 0xbfb95f0) // Thread "B" !?
In my code, the main() function instantiates a MainWindow, which in turn instantiates a HardwareManager and stores it as a private variable. When the HardwareManager is instantiated, it also instantiates the QSerialPort instance so it can properly talk to the COM port.
However, you'll notice above the my QSerialPort is in a different thread than the parent object, as well as it's parent object (It's in Thread B, while both ancestors are in Thread A). I think this other thread is causing my Signals/Slots to fail. If I dumpObjectInfo, it lists my Signal/Slot as being set up, but the events never fire.
this->serial = new QSerialPort();
connect(this->serial, SIGNAL(readyRead()), this, SLOT(readSerialData());
Above is the code that I use to create the new serial port and connect it to the proper slot. The actual baud, parity, and data/stop bit configuration happens separately (and works properly, as tested in the example app provided by QtSerialPort).
Does anyone have any insight as to why this particular object (QSerialPort instance) is being instantiated in a different thread? I've tried "moveToThread" to switch the thread association, but nothing seems to work.
I've also made a post on the Qt Project Forums, but have had no useful responses yet.
Edit:
The following is the relevant code in the call chain:
// main()
QApplication a(argc, argv)
MainWindow window = new MainWindow(); // [1]
MainWindow.show();
return a.exec();
// MainWindow::MainWindow() [1]
this->toolController = new QtToolController(this);
HardwareManager *manager = new HardwareManager(this->toolController); // [2]
// HardwareManager::HardwareManager() [2]
this->serial = new QSerialPort();
connect(this->serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
When a QSerialPort is ready to be read from (it has data to provide), it fires the readyRead signal (at least, it's supposed to). This signal fires properly in the Qt example projects, but I never get the signal in my application. I believe the reason I'm not getting the signal is because of these thread issues.
You could use QueuedConnection for catching signals from a different thread.
connect(this->serial, SIGNAL(readyRead()),
this, SLOT(readSerialData()), Qt::QueuedConnection);
This way, the slot should be executed in your main thread's context once the control returns to it's event loop.
Also, this post seems to suggest that you should not set a parent for the QtSerialPort (propably because moveToThread doesn't work on QObjects with parents).
In the spirit of keeping answers available to anyone else who encounters this problem, the issue was related to Release/Debug builds. The QtSerialPort library had been built ONLY for my Release environment, and for whatever reason, when running my application in Debug mode would link to the Release QtSerialPort, and thread contexts would get lost.
To fix this, I ensured I had built the proper version of the library, and then ensured I linked to the right version for my environment.
Related
I am using a 3D rendering C++ API and want to use Qt to display GUIs on top of it.
My rendering API runs in the main() application thread, just like Qt wants.
At first I tried to run Qt in it's own std::thread and it worked perfectly fine - and I have no idea what Qt's doc means with
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
https://doc.qt.io/qt-5/thread-basics.html
This is either plain wrong or poorly written...
My std::thread worker looks something like this:
int SomeClass::qt_app_worker(size_t width, size_t height, const std::string& title, const std::string& contents) {
int argc = 0;
QApplication app(argc, NULL);
// QDialog here
return app.exec();
}
The problem is then I can't do anything with this Qt app because if I try to create say another QDialog from the main() thread, Qt will complain I can only do this from the thread owning my QApplication (qt_app_worker).
So I'm either permanently locked out of the qt_app_worker thread, or I have to implement my own message queue for EVERYTHING Qt-related.
I sketched it with a derived QApplication class using startTimer() and then handling custom messages in timerEvent(...) but this is just too much hassle.
I just don't understand why Qt won't let a user run it in a separate thread, hopefully I'm just missing something.
There are (at least) two built-in thread-safe ways to communicate with the GUI thread (which is usually the "main thread" of Qt application, which is why it is often called main thread, and for Qt point of view it is).
You can post events (including your own custom event subclasses) to the thread using QCoreApplication::postEvent.
You can invoke methods of objects in another thread, provided you do so with Qt::QueuedConnection or Qt::BlockingQueuedConnection connection type using QMetaObject::invokeMethod (and its different overloads).
Communication the other way, from Qt to you own main thread, can happen in a few ways. I believe using Qt::BlockingQueuedConnection also allow getting a return value, but you probably don't want that blocking.... So you can just use any of the usual methods of communicating between threads, not limited by Qt, such as simply atomic or mutex-protected variables which are set from Qt, and your threads polls or otherwise reads when relevant (such as at start of every frame). Or make a simple message queue, if you want to be able to track every change and not just the state at the start of a frame or whatever.
I have the follow constellation:
A qt gui thread with MainWindow
Another thread which essentially is a CameraManager...everytime a camera is added/removed the MainWindow will be informed.
It roughly looks like this:
Mainwindow derives from ICameraAddedConsumer
MainWindow implements ConsumeCameraAdded and creates widget inside this function. It subscribes itselv as a consumer to the CameraManager
CameraManager calls ConsumeCameraAdded of all it's consumers (MainWindow) when a new camera is added.
The problem is that CameraManager lives in a different thread and Qt will obviously complain about this since a widget is not created in the same thread as the mainwindow was.
Any suggestions how I can solve this?
As per comments, using signals/slots between QObjects in different threads should take care of the issue "automagically."
Barring that, and assuming MainWindow/ICameraAddedConsumer is a QObject, one idea could be to use something like:
QMetaObject::invokeMethod(consumer, "ConsumeCameraAdded", Qt::QueuedConnection, ...)
where consumer is a pointer to the MainWindow/ICameraAddedConsumer instance.
There's QWaitCondition but I'm not sure that makes sense in this case (though it could be adapted I suppose).
Otherwise... don't create the widget in ConsumeCameraAdded() but set some flag there (and return) and then use a QTimer or QObject::timerEvent() to periodically check the flag and create widget if it is set. Unfortunately I'm pretty sure you will not be able to create or start a timer within ConsumeCameraAdded() itself because of threading issues.
I am using a third party library which takes 60-90 seconds to dynamically load several libraries. It is an unfortunate design choice, but I can't change who the built their code.
I am trying to use a QSplashScreen to at least tell the user to wait while I'm doing this one-time loading in the background. The problem is that the splash screen is not painting. I can see a window of non-painted space while the library loads. I can see the splash screen afterwards before I close it.
I looked at similar questions (e.g. Qt Splash Screen not showing) but nothing seems to resolve my problem. I have tried loading an empty QPixmap and just giving it a solid color. That doesn't show up either.
QApplication a(argc, argv);
QPixmap pxl("icon.bmp");
QSplashScreen qss(pxl);
qss.show();
qss.showMessage(QString::fromStdString("Please wait... Loading"));
a.processEvents();
MainWindow w;
//thread is blocked
w.preLoad();//this is where the lengthy process takes place
w.show();
qss.finish(&w);
I'd like to ensure that it at least paints once before I start my loading process.
------------------------EDIT-------------------------------
Let me reiterated that the call to preLoad is BLOCKING the thread. This is not an option. I have tried a separate thread for that process. I have tried with a separate thread for the splash screen as well (turning it on and then finishing whne the other thread is done). I have tried using semaphore between the two threads to accomplish this and while everything works (including the splash screen) it takes 200-800 seconds to load. That is simply not acceptable. Thus I would like to see if there is away around it from this perspective.
-------------------------Final solution--------------------------------
Thanks to the comments below I was made aware that Qt has its own threading functionality. All the problems I was seeing appear to be caused by the interplay of std::thread and Qt's own implementation.
I have a partial solution which does work. It's not as neat as it could be, but I wanted to include it in the question thread.
//in the main method code described above
MainWindow w;
w.preLoad();
while(w.IsLoading())
{
//waiting on semaphore signaling loading is complete
//this part could probably be done better with QThread
//and signals, but it is a quick fix for now
std::this_thread::sleepfor(std::chrono::milliseconds(500));
a.processEvents();
}
w.show();
qss.finish(&w);
//In the MainWindow class
void MainWindow::preLoad()
{
loading=true;//semaphore to stall main thread
QFuture<void> future = QtConcurrent::run(this, &MainWindow::LongMethod);
}
void MainWindow::LongMethod()
{
thirdPartyLibrary.impossibleCall();
loading=false;//this handles my semaphore
}
Every GUI is executed in an infinite loop, so Qt also uses it, but the blocking tasks generate that the loop is not executed correctly, showing inadequate behaviors like the one you observe.
If one wants to execute blocking tasks it is advisable to execute it in another thread for it Qt provides several possibilities:
QThread
QThreadPool and QRunnable
QtConcurrent
I recommend the following link for you to choose the right option for your case.
If you want to update the GUI view with the information generated in another thread it is advisable to use signals and slots, or use QtConcurrent.
GUI Thread and Worker Thread
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.
Another way is to force the GUI to update for this we can use qApp->processEvents().
References:
http://doc.qt.io/qt-5/thread-basics.html
http://doc.qt.io/qt-5/threads-technologies.html
i am at the moment really confused about threading in QT. I read so much different opinions which i can realize this.
I have a class (Computations) which do heavy computations and generate a lot of solution. When this class find a solution i call with help of
boost::function<void (Solution)> f;
a custom function. Which can be bind with
f = boost::bind( &MainWindow::FoundSolution, this,_1);
No i have my mainwindow in QT. There i call my class Computations with
Computations comp(f);
QFuture<void> future = QtConcurrent::run(comp,&Computations::DoSomethink);
So it compute while i can use the GUI and i get the response of new solutions to the FoundSolution function in my mainwindow. In this function I use QGraphicview to draw my solution. The Qgraphicsview is a member of my Mainwindow.
This works sometimes.
But i often get the following error
Assert failure in QCOREApplication::SendEvent: " cannot send events to
objects owend by a different thread. Current thread 438bc40. Receiver
" (of type "Qgraphicsscene) was created in thread 15dcc00, file
kernel\qcoreapllication line 494
This mean i call my GUI application from a thread which is not the main and this is forbidden by QT. But with my boost bind i should be in my main thread or? And why it works sometimes ?
Do you know a better implementation for this? I am really new with QT and threads.
Thank you for your help.
If you emit a signal from you worker thread that is connected to a slot of an object that lives in the ui thread, the slot will be executed in the ui thread.
So basically if you want to draw a new point in the QGraphicsView, send a signal from your worker thread passing in the coordinates of the new point to draw. The signal need to be connected to an object that lives in the ui thread. The slot will then handle drawing the new point in the QGraphicsView which will work since the slot is executed in the ui thread.
For more information see Signals and Slots Across Threads
The normal way to do this is to use signals and slots. You can find some documentation, which is specific to your problem, here: Qt 4.8, Qt 5.
connect( &sender, SIGNAL(), &receiver, SLOT(), Qt::QueuedConnection)
The easier fix is to add Qt::QueuedConnection to the problematic slot connection call.
I will keep the code simple so that you guys can see what I'm trying to do ;)
I am aware of all of the locking issues, etc. I'm trying to figure out how signals and slots play with threads.
In main.cpp:
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MyConsole c; // Subclasses QThread and implements run()
MyReceiver r(app); // We pass app to MyReceiver for later (see below)
QObject::connect(&c, SIGNAL(sendit()),
&r, SLOT(gotit()));
c.start(); // Start the worker thread
app.exec();
}
Assume that the signals and slots were properly set up in the header files (I've tested and they are). Now, here's the issue:
In MyReceiver.cpp:
void MyReceiver::gotit()
{
QLabel *label = new QLabel(0, "Hello"); // Some GUI element, any will do
app.setMainWidget(*label); // Some GUI action, any will do
}
The question is: Because the MyReceiver object was created in main(), which is on the main thread, does that mean that the slots (e.g., gotit()) will run on the main thread and are therefore safe for doing GUI stuff? Even in cases where the signal was raised from a different QThread (like MyConsole in this example)?
Is there a better way to allow worker threads to interact with the GUI (for example, Obj-C/Cocoa have a "send message on main thread" type of approach). What is "The Qt way" of doing this?
Thanks in advance!
By default (Qt::AutoConnection), slots will run in the thread the QObject was created in. So, no matter from what thread you emit the signal, the slot will be run always in the thread, the QObject "lives" in (if a Qt event loop is running in that thread, otherwise the event can't be delivered). Since the main thread will become the Qt GUI thread, this will work as expected. This is indeed the Qt way of interacting with the GUI.
See also: http://doc.qt.nokia.com/4.7/thread-basics.html (look for thread affinity).
The "Qt way" to emit a signal from one thread and receive it in a different thread is to use a Queued connection
connect( obj, SIGNAL(foo()), other_obj, SLOT(bar()), Qt::QueuedConnection )
From the Qt documentation for Qt::QueuedConnection:
The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.