Multithreading Crash using QT and QOGL - c++

I have an QOGLWidget widget which is constructed in a another window, which is activated by button from the QMainwindow.
I'm trying to send a surface of an image from the widget to the main window's QOGLWidget, the problem that it crashes and gives a first chance exception access violation.

There are three things that I think may be going on in this situation:
Qt::AutoConnection
Your connection between your frame generator and the GUI (SimulatorWindow + GLSimulatorWidget) are connected by Qt::AutoConnection and ends up turning into a Qt::DirectConnection when they reside on separate threads. Specify a connection of Qt::QueuedConnection to overcome this problem (if indeed they are on separate threads).
QPixmap v. QImage
You could be handling QPixmaps off of the GUI thread. This usually will print out a warning, but maybe still function. In general if your processing an image not in the GUI thread, and then sending it to the GUI thread, you need to use something besides QPixmap, like QImage.
Initialization on the Stack
Your frame object may be going out of scope by the time it gets to your GUI. For example, if you build a frame, and store it in a local scope on the stack, and you pass it into a handler or a container...
...then when you leave the local scope to representing the object in the GUI, your frame object will be gone and your handler/container is left holding a bad pointer.
To fix this, initialize onto the heap and stick to the Qt Object Model. Also I like to make my containers on the heap also as member variables to the class they belong to.
So in summary:
Check your connection types and if your frame generator is on the GUI thread or not, use QImage not QPixmap if you are in a thread that is not the GUI, and make sure your pointers are not going out of scope.

Related

Pixmap shared between threads in Qt

I've got a main GUI class and another Worker class: the first copes with GUI things (drawing a QPixmap into a QGraphicsScene), the second with computations thing (drawing QLines and QPoints onto that QPixmap).
The two classes run in two different threads.
When I create the Worker thread, I pass the address of the GUI's QPixmap to the Worker class, so they share the same object.
The QPixmap is modified in the Worker class, and drawn in the GUI class. Even if I didn't have any problem, I decided to use a QMutex to ensure my program wouldn't try to access the QPixmap while it was being drawn. Now, in order to do this, I have a QMutex shared between GUI class and Worker class (Worker class has again a pointer to the GUI's QMutex). Whenever I read or modify the QPixmap I lock the QMutex.
Is this a valid approach? I never got errors so far, but I wonder if it is logically correct and whether Qt provides a better way to accomplish this.
Thank you in advance.
According to the Qt5 thread-safety page:
QPainter can be used in a thread to paint onto QImage, QPrinter, and
QPicture paint devices. Painting onto QPixmaps and QWidgets is not
supported.
So the official line is no, you should not be modifying a QPixmap outside of the main thread. You may be "getting lucky" in that it happens to work on your current platform under your current use case, but Qt doesn't guarantee that it will work.
A safer approach might be to have your worker thread draw into a QImage object instead, and then when the GUI thread wants to update the GUI, it can grab and draw the latest version of the QImage object (using mutexes or some other mechanism to make sure that the worker thread isn't simultaneously updating the QImage).
I agree according to the documentation, it's not allowed to use QPixmap in a worker thread. However, according to the code.
The constructor checks if it's in the main thread. If it's not in the main thread, it checks for a feature called ThreadedPixmap. If enabled, it will continue without problem. As far as I can see, ThreadedPixmap is supported on all platforms, so it seems possible to use QPixmaps on other threads.

Qt - Working with Threads

I have a QTimer for executing OpenCV code and changing an image in a QLabel every 20 milliseconds, but I want to run this OpenCV code more naturally and not depend on the timer.
Instead, I want to have one main thread that deals with user input and another thread that process images with OpenCV, what I can't find is a thread safe way to change the QLabel image (pixmap) in one thread from another thread, could someone describe this process, maybe give some code examples? I also want to know the pros and cons of using QThread, since it's plataform free, it sounds to be user level thread and not a system level which usually runs smoother.
You can only instantiate and work with QPixmap on the main (GUI) thread of your application (e.g. what is returned by QApplication::instance()->thread())
That's not to say you can't work with a QPainter and graphics objects on other threads. Most things work, with exceptions guided by constraints imposed by the OS.
Successive versions of Qt have managed to find ways to support things that previously didn't work. For instance:
Qt 4.0 added rendering QImages from separate threads
Qt 4.4 added the ability to render text into images
Qt 4.8 added the ability to use QPainter in a separate thread to render to a QGLWidget, QGLPixelBuffer and QGLFrameBufferObject
Where Qt 4.4 introduced QFontDatabase::supportsThreadedFontRendering to check to see if font rendering was supported outside the GUI thread, in Qt5 this is considered obsolete and always returns true
Note: you shouldn't hold your breath for the day that Qt adds support to work with QPixmap on non-GUI threads. The reason they exist is to engage the graphics layer directly; and finding a way to work around it just so you could use something named QPixmap wouldn't do any good, as at that point you'd just be using something equivalent to what already exists as QBitmap.
So all that has to do with the ability to instantiate graphics objects like QFont and QImage on another thread, and use them in QPainter calls to generate a graphical image. But that image can't be tied directly to an active part of the display...you'll always be drawing into some off-screen buffer. It will have to be safely passed back to the main thread...which is the gateway that all the direct-to-widget drawing and mouse events and such must pass through.
A well known example of how one might do this is Qt's Mandelbrot Sample; and I'd suggest getting started with that... making sure you understand it completely.
Note: For a different spin on technique, you might be interested to look at my Thinker-Qt re-imagining of that same sample.

OpenCV's highgui in C++ Qt application

I am trying to combine OpenCV's webcam access and image display functions with Qt's Network capabilities (Qt 4.8.1 C++ console application using OpenCV 2.4.2 highgui).
I am currently trying to avoid converting a cv::Mat to a Qt format and displaying it by custom Qt GUI for simplicity.
For this, I am creating a wrapper class that does all the OpenCV stuff (cap = new VideoCapture(), namedWindow(), cap->read(), imshow(), destroyAllWindows(), cap->release()) controlled by a QTimer an move it to a QThread.
This mostly works (still garbage characters in the window title) but sometimes OpenCV creates a new window when the thread's parent class is receiving signals from its QTCPServer.
This results in "dead" image windows that are not updated anymore.
The order of creation (OpenCV thread / QTcpServer) does not seem to matter - however, if no client connects, I can see that OpenCV creates a small window first, that consequently gets enlarged to fit the video image size.
If a client connects, the smaller window most of the times remains (Window title garbage like "ét), the newer window receives the image data properly (Window title garbage like ",ét").
Not moving the OpenCV wrapper object to a thread does work as well, but the same problem occurs (even worse, two dead windows are created, the second of which already received an image frame).
What could I generally be doing wrong to cause such behavior?
I suspect that the problem may be caused by the named window being created and accessed in two different methods of my QOBject wrapper class (Constructor and slot).
Or the QTCPServer is blocking the Qt event loop? Or that the OpenCV window handle is "garbage-collected" for some reason, when the Signal-Slot mechanism is triggered by QTCPServer events, and then imshow creates a new window?
There is no obvious way of accessing the window by pointer, so this must be the reason. Removing the initial namedWindow() does away with the small, empty window but still, two windows are created.
It seems I have to convert and display the images myself after all - or is there another way?
I think the problem here is encapsulation, as far as I understand you are trying to display an image on the same window from two different threads, this is wrong. You should be displaying image from single thread and maybe you can create an image buffer at that thread and your other threads put images to that buffer and you can use that buffer to display images. If I understood it wrong can you explain your problem clearer?

Drawing from multiple threads in Qt

I'm writing a program in Qt, which runs 10 worker threads which calculate the trajectory of an object in space. They also have to draw the path of the object. I have a "Body" class deriving QGraphicsEllipseItem and it has a QPainterPath in it. The "Simulation" class takes a list of obstacles in the world, and the body to simulate and runs until the body collides with something. Simulation runs in a separate thread ( done with moveToThread, not by subclassing QThread). When the body collides, the Simulation emits a signal saying that it finished. When all threads have finished I'd like to draw the paths (I do it by invoking a method in "Body" which enables path drawing in its draw method).
Unfortunately I get ASSERT errors :
ASSERT: "!unindexedItems.contains(item)" in file graphicsview\qgraphicsscenebsptreeindex.cpp, line 364
They happen seemingly randomly. I've tried different connection types, to no result.
I'm starting the threads in a loop.
I'm using Qt 5.0
Generally speaking, with Qt you can't do any GUI operations outside of the GUI thread (i.e. the thread that is executing QApplication::exec(), which is typically the main() thread).
So if you have multiple threads manipulating QGraphicsItems (especially QGraphicsItems that are currently part of a QGraphicsScene), that is likely the cause of your assertion failures. That is, when the Qt GUI thread is doing its window refresh, it is reading data from the various QGraphicsItem objects as part of its calculations, and it expects the QGraphicsItems to remain constant for the duration of the refresh operation. If a QGraphicsItem is changed (by another thread) while the refresh routine is executing, then the calculations made by the main thread can become wrong/corrupted, and that occasionally causes an assertion failure (and/or other unwanted behaviors).
If you really need to use multiple threads, what you'll probably need to do is have the threads do all their calculations on their own private data structures that the Qt GUI thread has no access to. Then when the threads have computed their results, they should send the results back to the Qt GUI thread (via queued connection or QApplication::postEvent()). The GUI thread can then look at the results and use them to update the QGraphicsItems, etc; this will be "safe" because this update can't happen in the middle of a window update.
If that sounds like too much work, then you might consider just doing everything in the GUI thread; it will be much easier and simpler to make everything work reliably that way.
As mentioned by Jeremy, Qt rendering must be done on the main thread.
While you could move it all to the main thread, you've likely chosen to create separate ones for efficiency, especially as collision detection can be processor intensive. The best way to handle this is to split the modelling of the objects and their physics from their rendering, as you would in a Model / View / Controller pattern.
Create representations of the body instances that are not derived from any QGraphicsItem/Objects. These can then do their calculations on separate threads and have signals to graphics objects that are running in the main thread, which updates each body instance's graphic representation, allowing real-time rendering of the trajectories.

Thread type for background drawing to a bitmap in MFC

I have a MFC document/view C++ graphics application that does all its drawing to an off screen bitmap, and then copys that to the supplied CDC pointer in the OnDraw method. Over the last couple of days I've been looking to place the drawing component in a seperate worker thread, so it doesn't stall the GUI. I seem to get a fair number of MFC GDI related asserts firing when I do this, e,g,
VERIFY(::MoveToEx(m_hAttribDC, x, y, &point)
So a few questions;
Are there any problems with using worker threads with MFC & GDI?
Are there issues using MFC GDI objects across threads?
Do GDI objects have to be declared locally to a thread?
While it is possible the issue is resource/locking related, the drawing thread has its own provate CDC and CBitmap that it uses for all the drawing, and only copies the bitmap back to the main thread when it hasz excludive access via a mutex. The code has also been tested by direct calling rather than as a seperate thread to prove the problem does relate to threading.
Device contexts can be used by any thread (the only thing you must be aware of is that the thread which did the GetDC should also call ReleaseDC), but are not inherently thread safe. You have to ensure that only one caller is accessing the DC at any given point in time, but you seem to have taken care of that, from what you write.
What do you mean by Do GDI thread have to be declared locally to a thread ? They must be allocated and freed in the same thread, but they can be created/used in any thread. Once again, you are responsible not to use such a resource from two threads simultaneously.
You should probably check the series of posts from Raymond Chen on the subject:
Thread affinity of user interface objects, part 1: Window handles
Thread affinity of user interface objects, part 2: Device contexts
Thread affinity of user interface objects, part 3: Menus, icons, cursors, and accelerator tables
Thread affinity of user interface objects, part 4: GDI objects and other notes on affinity
Thread affinity of user interface objects, part 5: Object clean-up
and be sure that you don't link to the single threaded versions of the C/MFC libraries.
Raymond Chen has posted about this on his blog:
http://blogs.msdn.com/oldnewthing/archive/2005/10/11/479587.aspx
(There are other blog posts about thread affinity of windows objects which might be helpful to you).
Apparently for DCs you need to do the Get/Release on the same thread.
Hope that helps!