I'm experiencing some problems with my embedded application. It is a page that contains a QTimeEdit that counts the time each second, some checkboxes and some QLineEdits that refresh each second.
After some minutes of working, I see a freeze of interface, even if the application is still running. If a try to press buttons or checkboxes an access violation message appears:
Exception 'Access Violation' (14): Thread-Id=05d80002(pth=8af6109c), Proc-Id=04a90002(pprc=91431714) 'nmb3.exe', VM-active=04a90002(pprc=91431714) 'nmb3.exe' PC=407ea307(qtgui4.dll+0x0005a307) RA=40d6c82c(qtgui4.dll+0x005dc82c) SP=01c1b928, BVA=00000004
The exception is related to qtgui4.dll. I checked if a saturation of virtual memory occurs, but this is not the problem that causes the freeze.
The freeze doesn't occur if I avoid to update the QTimeEdit, but I don't understand why.
You should move the timer into the mainwindow class, keeping the sensors handler in the separated thread.
The sensors handler should:
store the data
emit a "data ready" signal to the window
Then the timer in the mainwindow, every second, will:
read the data from the sensors handler
update the GUI
(make sure you are using thread-safe objects or, managing the critical sections)
Related
I'm working on a project, which is a C++/Qt desktop application. In this application, I've identified a certain problem related to the execution of interface events.
For example, in this application, the mousePressEvent delegates a certain operation to the program, and this operation can be slow sometimes, so if the user presses the mouse button before this operation ends, the program begins to execute another operation before the previous one finishes.
Does anyone ever have this same issue with Qt?
Thank you.
In my MFC application , I am using TCP/IP socket for communcating and getting data from a server.During this process I am displaying a modelless dialog with static text and progress control.During communication I am updating the static text and progress control in a separate user thread(AfxBeginThread).
If I try to communicate to wrong ip the sockets select function with timeout value 5 secs blocking the displaying of dialog with static text and progress control(I.e the dialog hangs, the controls are getting displayed).
Once the socket comes out from select function the dialog is getting displayed properly.
How to fix this problem?
In MFC, I'd strongly recommend using CAsyncSockets, and just reacting when data comes in from the server. You probably have no need to spin up a thread at all.
If you were going to spin up a separate thread for part of the job, you'd want to allocate tasks to threads somewhat differently. You always want to leave UI updates in the main thread (the one that was created by default). If you were going to use (for example) a blocking socket, and call select on it, you'd want to move that work to a separate thread, and leave the UI updates in the thread that was created by default. Then the thread handling the socket could (for example) send messages to the UI thread to tell it about what's going on, so it could update the UI appropriately. But, as already noted, you probably just want to use a CAsyncSocket, in which case you won't need a second thread at all.
I have a CListCtrl in my MFC application. The list needs to be updated when I get some notification from the server. Updating list works quite good when there are less notification as operations on the list are less. But in case of heavy load, list control and in turn the application gets freeze.
I am aware of updating UI items in the separate thread in case of bulk updates, but in this case I have the notifications that can come in any order and in any volume, I need to handle in such way that my main thread is not getting blocked.
If anyone faced the issue before please suggest the approach for this case.
You could put all the updates into a queue. Then do a limited number of updates from the queue to the control in the OnIdle function. OnIdle is called when your GUI message queue is empty. It could do up to, say, 20 updates and then return. The main thread would than process any GUI input and when finished with that it would call OnIdle again. In this way you delay and spread out the updates while keeping the GUI alive.
I had a similar situation and resolved it using a Timer. Only when the Timer ticked the ListCtrl could got updated.
Side note: You should do
SetRedraw(FALSE);
before a bulk update
and
SetRedraw(TRUE);
after.
You should not have the control drawing itself at a one-by-one item level, when doing a bulk operation.
Use Thread.I had the same problem and I solved it by just having the loop of adding elements into the clistctrl in thread function. That is,is the POSTMESSAGE() function in the thread should be called as much time as we want to add elements .
MFC Application getting stuck when adding list control elements
Also refer the above link to get some idea
I written an exception handler routine that helps us catch problems with our software. I use
SetUnhandledExceptionFilter();
to catch any uncaught exceptions, and it works very well.
However my handler pop's up a dialog asking the user to detail what they were doing at the time of the crash. This is where the problem comes, because the dialog is in the same thread context as the crash, the dialog continues to pump the messages of application. This causes me a problem, as one of our crashes is in a WM_TIMER, which goes off every minute. As you can imagine if the dialog has been on the screen for over a minute, a WM_TIMER is dispatched and the app re-crashes. Re-entering the exception handler under this situation is bad news.
If I let Windows handle the crash, Windows displays a dialog that appears to function, but stops the messages propagating to the rest of the application, hence the WM_TIMER does not get re-issued.
Does anyone know how I can achieve the same effect?
Thanks
Rich
Perhaps you could launch a separate data collection process using CreateProcess() when you detect an unhandled exception. This separate process would prompt the user to enter information about what they were just doing, while your main application can continue to crash and terminate.
Alternatively, if you don't want to start another process, you could perhaps create another thread with a separate message queue, that blocks your main thread from doing anything at all while the dialog is on the screen. While your main thread is blocked it won't have the opportunity to handle WM_TIMER messages.
Show the dialog in a second thread.
I had more or less the same problem (but had to show a message box rather than a dialog).
Write a class in which you create two events using the Win32 CreateEvent function. One event (trigger) is used to trigger the dialog, one event (ready) is to signal that the dialog was handled.
Add a method 'execute' to the class and start this method in a second thread
Let the 'execute' method wait until the trigger event is set, and if it is set show the dialog
After the dialog has been handled, set the 'ready' event.
If your application crashes in the main thread, prepare some information for the dialog (via setters in the class) and set the 'trigger' event, then wait for the 'ready' event. The set'ting of the trigger event will activate the second thread, and the main thread will block until the second thread has set the 'ready' event
I'm New to QT. I understand that you can force a display refresh, but I've pulled all my hair out trying to figure out how. Here is what I'm specifically trying to do.
I press a button (onClick signal event), which runs code that changes an image (QLabel) on the display, waits for input, and then proceeds by changing a new image (different QLabel). I've tried everything and the display doesn't refresh until the onclick signal event code is complete. Right now, I'm not waiting for user input, I'm using usleep(~500 ms) for testing purposes.
From what I read, QT is event driven meaning that I'm basically creating a bunch of events, that get put in a que, and executed when the (onClick signal event) returns to the (main loop)/(event handler). I don't want to wait until the function is complete, it's going to make programming extremely painful if I have to accomplish this routine entirely based on events.
How can I force the QLabel pixmap to refresh. I've tried everything. Below is all the code I have tried in my onClick signal event handler. (upButton is the name of the QLabel which is a pixmap)
update();
repaint();
ui->upButton->setUpdatesEnabled(TRUE);
update();
repaint();
QPaintEvent paintevent(ui->upButton->childrenRegion());
QPaintEvent * test = &paintevent;
paintEvent(test);
this->changeEvent(test);
ui->upButton->update();
ui->upButton->repaint();
ui->upButton->repaint(ui->upButton->childrenRegion());
repaint();
QApplication::sendPostedEvents();
this->parentWidget()->update();
usleep(100000);
As you can see, I'm just shooting in the dark at this point. I've tried to look at sample code and do all my homework, but I'm lost. Appreciate any help, advice, and or sample code.
I was using sleep to emulate a brief amount of time the computer was waiting for something to happen.
As I stated in my question, I didn't want to use events because it's a whole lot of unnecessary work to accomplish something extremely simply.
Also, the 'event' that needs to take place for the program to continue, is a USB event. Since I'm using an HID class device, there is no way to set an event to happen without a wait loop. USB HID classes don't permit setting interrupts, the OS claims the device.
I managed to get the above to work. I walked through the debugger and noticed the display would refresh before the sleep function. Running the program independently, I got random results with the display refreshing 1% of the time. I got rid of the sleep function, and added some other code in it's place to emulate a delay, and it was fine.
Just for everyone's knowledge, this is possible, it's not forbidden, and it's easy to do with the following:
qApp->processEvents();
qApp is a global external variable in the QApplication header.
Because this USB event is making my flow tricky, I stumbled upon the QWaitCondition Class. I was going to start a process waiting for the USB event. I would wait until the process releases the wait condition for my routine to continue.
But if anyone thinks this is a bad idea, please, speak out. I really do appreciate your feedback PiedPiper and Hostile Fork.
Thank you.
I noticed sometimes when you have multiple layered widgets, or widgets inside of widgets it helps to call their repaint() events.
For example
this->repaint();
this->parentWidget()->repaint();
this->parentWidget()->parentWidget()->repaint();
This is far easier then pushing out any processing to another Thread, or creating additional event handlers.
You shouldn't be waiting for input in your event handler. You need to rethink the logic of your program to use events the way they were intended. All the update() and repaint() calls in your code are unnecessary if you return to the event loop.
If i understood correctly, you have a slot and in this slot, you update the image shown in a QLabel. But you want this change to be displayed before the slot finishes.
If that is the case, issue an update() event, and call qApp->processEvents(). This method processes events that are waiting in the event queue and then returns, therefore this may be what you are after.
PS: an update() may not be necessary at all, i am not sure.