I am using Qt for developing a custom control interface to xmgrace, a 2D plotting library.
I have 3 components in my project:
A GUI made in Qt
A QThread which runs some shared object code from C in a background thread.
An xmgrace window connected to both the above using a pipe. (Using the grace_np library)
Communication from (1) --> (2) is done by changing status of some global variables declared in the shared object code.
Communication from (1) --> (3) & (2) --> (3) is using built in functions provided by the grace_np library.
Now, communication from (2) --> (1) is what is causing problems. I tried 2 possible ways I could think of:
a) Declaring a shared object in Qt code which emits a Qt Signal and is called within the C code.
b) Returning from the thread and using the return value to perform some operation and then restart the thread.
Both these methodologies have given unreliable results. My GUI gets stuck/causes segmentation fault and I get the message:
QProcess: Destroyed while process is still running
I am not using the QProcess class anywhere in my code. So this has become a mystery.
Please provide some info on what could be the possible causes for this.
PS: The pipe to (3) is one way and is required that way only.
Edit 1:
FYI I'm using Qt 4.2, So I can't use the QObject approach and then use a movetothread()
I'm sorry for not putting the code, as I can't due to company policies and also because I don't know what to put (Its too huge). The shared c code is 400k+ lines
I believe I have found the culprit to my problem. It seems that using the class QMessageBox is causing this problem. I was initially using static function of QMessageBox. Now I have tried declaring it over both the stack and the heap, but the problem still persists.
But I have found that removing all calls to QMessageBox from my code solves the problem.
But then the problem now is, how do I show messages?
I am just speculating here, but is it possible that the modal nature of QMessageBox is blocking the pipe existing between my program and xmgrace and subsequently causing it to quit? Then creating a custom QMessageBox (non modal) might solve this issue.
Edit 2:
I'm not calling the QMessageBox from the worker thread. Plus the way I'm using the worker thread, it never returns unless I close the program. To give an idea my QThread::run function is of the form:
QThread_Object::run()
{
c_init();
c_main();
}
where c_init & c_run are functions linked from shared c code. So it is impossible to call a QMessageBox from within these directly.
For now I'm planning on doing away with the QMessageBox and using the QMainWindow status bar instead. But then it doesn't give the entire functionality. I suppose this could be a bug in Qt 4.2
Edit 3:
I mentioned earlier that communication from (2) --> (1) was what was causing problems. Now I have done away with this communication completely and have discovered more precisely that the problem is caused by invoking QMessageBox anytime after starting the worker thread. Earlier the communication mentioned above was causing Qt to emit a signal indirectly and invoke a QMessageBox which I believe was the culprit.
Edit 4:
Ok, I forgot to mention the biggest mystery surrounding this problem since the beginning. I basically work(Place A) via ssh on a workstation(Place B) on which I code and run this program.
B is connected on 2 physical networks. A is connected to B through Network 1. Now this problem has never occured while working from my terminal at A (ie on ssh via Network 1). But it consistently occurs when I access B directly or through ssh over Network 2. Please note that every time the code is executed on B only. Both these networks are used by hundereds.
Edit 5
Finally, I have solved my problem by sub-classing QDialog and making a custom MessageBox as I don't really require the extended functionality of QMessageBox. I still don't know what precisely within QMessageBox was causing the problem. I suppose some bug within Qt which will always remain a mystery.
Since there's no code I'm shooting in the dark a little here, but it sounds like your QProcess was created on the stack, intentionally or not, or your QThread is getting destroyed prematurely. I'd put money on your QThread objects being launched incorrectly. It's hard to blame you since the documentation is (or was until recently) screwy. Consider reading this thread and this thread and don't sub-class QThread at all.
Edit:
If QMessageBox is your culprit, then I'm guessing that you're displaying it from the child thread. From the documentation:
In GUI applications, the main thread is also called the GUI thread
because it's the only thread that is allowed to perform GUI-related
operations.
There are several ways to display messages from a child thread. Personally, I use qt's error reporting scheme and redirect qCritical, qDebug, etc to stderr. Another easier way to do it would be for you to emit a QString signal from your worker thread that's caught by your GUI thread, which then displays/collects the error. I like to have my MainWindow collect the errors and then display them all at once when the worker thread finishes.
Edit 2:
Since the problem seems to be QMessageBox being modal (i.e., blocking your main thread while the worker thread moves forward), you can easily solve this by using QMessageBox in its non-modal modes. Simply pass 0 as the parent widget in the QMessageBox constructor/static function. Processing will continue without waiting for the user to exit the window--this might also result in multiple message boxes being open at the same time. If that helps you avoid the error, go over your code carefully to make sure the windows are properly destroyed after closing.
Related
I have an entertaining problem to solve. I use Qt 5 for one of my projects for reading information on the network. I read modbus devices and stuff, but the real problem comes when the network isn't available.
The interface freezes and I can't interact with it. The network stuff is done in a separate thread or that is what I think. Here is some code example:
class TwidoDevice : public QObject
{
Q_OBJECT
public:
explicit TwidoDevice
........ And some useful code
The use of the (main interface) class in Window.cpp is:
L1Thread = new QThread();
L1Thread->start();
L1TWD = new TwidoDevice(L1TWD_settings,
L1TWD_Name,
PercentRegisters,
TotalsRegisters,
db, 1);
L1TWD->moveToThread(L1Thread);
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()), Qt::DirectConnection);
In this code startFired() start reading the devices on the network.
In some other function in Window.cpp:
emit startReading()
When this code is executed the interface freezes even though I've moved the L1TWD object to QThread.
When I try to debug it using the built-in debugger in QtCreator, I can't seem to understand whether the object has been moved or not and why the interface is frozen during the network call.
Has any one encountered the same problem and what is the way to solve this?
Thank you for spending time reading my question!
This is the main problem:
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()), Qt::DirectConnection);
You are connecting the receiver and sender in different threads with direct connection, which will block the UI. Given that your slot execution gets stuck, this is expected. You have at least two issues here to solve.
Use the default connection which will not block across threads, just inside the same thread. So, you would be writing something like this:
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()));
Secondly, you could make sure that your thread does not get stuck when there is some "network" problem.
For debugging purposes, please print out the current thread when having this kind of threading issues using the following methods:
[static] QThread * QThread::​currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
and this:
[static] Qt::HANDLE QThread::​currentThreadId()
Returns the thread handle of the currently executing thread.
Warning: The handle returned by this function is used for internal purposes and should not be used in any application code.
Warning: On Windows, the returned value is a pseudo-handle for the current thread. It can't be used for numerical comparison. i.e., this function returns the DWORD (Windows-Thread ID) returned by the Win32 function getCurrentThreadId(), not the HANDLE (Windows-Thread HANDLE) returned by the Win32 function getCurrentThread().
You are using a Qt::DirectConnection for your connection, which means the slot is called immediately, i.e on the same thread as the signal was fired. You can have a look at the documentation for ConnectionType. What you want to use is probably Qt::QueuedConnection, which executes the slot in the thread of the receiving object.
The best way though, as lpapp pointet out, is to let Qt decide what is best, and simply use Qt::AutoConnection, which is the default. It will use a QueuedConnection if signaling and receiving threads are different, and DirectConnection otherwise.
[I might be wrong about these]
TIdTCPServer Server is multithreaded in Borland C++ builder. It handles all client's on seperate threads. This is written in help of Borland c++.
Now is my problem & question.
For example, ShowMessage(String ..) method should be called on main (gui) thread. But as I say above, TCPServer is multithreaded and handles OnExecute event on different threads. When I use ShowMessage method in OnExecute event (which is handled on a different thread than main thread), I get weird results. Sometimes ShowMessage() works as expected, sometimes it is shown without any text on it with different box sizes(infinite lengt, very long, normal, etc). The other user interface changes causes no problem(update TEdit, TMemo. Only ShowMessage() has problem for now)
I think this problem is the result of calling ShowMessage() method not on the main (gui) thread but on TCPServer's thread which is created for client connections internally by TIdTCPServer.
So how can I fix it?
ShowMessage() displays a VCL TForm, and as such is not thread-safe. You have to use TThread::Synchronize(), TThread::Queue(), TIdSync, TIdNotify, or any other inter-thread communication mechanism of your choosing to make ShowMessage() run on the main thread.
To display a popup message in a worker thread, use the Win32 API MessageBox() function instead. It is thread-safe, and can be called in any thread without synchronizing with the main thread.
All changes to the user interface should be done in the main thread. You can use the TThread::Queue function for executing a function in the main thread. It posts a message to the main message queue, and the TThreadMethod passed as a parameter gets executed when the main thread handles messages.
If you need to pass data to the main thread, e.g. the message to be shown, you'll have to do that separately, as function parameters cannot be passed via the Queue function.
Yes your issue has most probably nothing to do with TCP. Any VCL access must be done within the main thread. (do not forget that message dialogs are often called from VCL wrapers and not directly through winapi)
Yeas I know it sometimes works 'well' even when not, but then this issues appears:
always an exception an App close/exit
occasional App hang/exception (fatal or non fatal for App)
occasional corrupted VCL visual stuff (missing items in lists, missed events, etc)
occasional unpredictable behaviour (sometimes overwrite even App non VCL data)
Many occasional issues are repeatable dependent on:
UI complexity
source code complexity (bigger code more often issues)
number of windows/forms
Also beware of memory leaks. VCL is extremly unstable if memory manager is corrupted by invalid deletes etc... (do not know how about it in newer versions but in bds2006 is this very big issue)
PS. if you need just dialogs then use WINAPI interface it should work even in threads if your text data is not VCL related (for example AnsiString variable access is fine but DBGrid access is not)
I made a MFC application which probably has two threads, one for receiving data from a socket using UDP protocol and one is the main thread of MFC app. While any data is received some objects, created in the main thread by new operator, would be notified to fetch the data through apply the observer design pattern. The problem is that sometimes after I clicked the close system button, the GUI of the app disappeared, but its process can still be found in the Task Manager. If I stop the data source (UDP client) this problem would never happen. Other important and maybe helpful information is listed below:
The Observer design pattern was implemented with STL container list. I have used the critical section protection in the Attach, Detach and Notify functions.
I deleted the observer objects before closing the UDP socket.
The data transfer rate may be a little faster than process data, because after closing the data source the data process is still working.
I can't figure out what lead my app can not exit completely. Please give me some clues.
This is usually caused by a thread you created and not exit it programmatically when you exit the appliation. There must be a while clause in your thread. The way to find where it is still running is:
use debug mode to start you application and click the exit button the top right corner to exit it.
Check from task manager and see if it is still running
if it is, excute Debug->Break All,
Open threads windows, double click each thread, you will find where your code is still looping.
Typically a process won't terminate because there's still a foreground thread running somewhere. You must ensure that your socket library isn't running any thread when you want to close your application.
First thing, with MFC, please use the notification based methods to get notifications on message arrivals, connections etc. So you can get rid of threads if you have.
It's quite easy to attache to a debugger and Break see which threads are existing and waiting for what.
Alternatively you can use ProcessExplorer with proper symbol configuration to see the call stacks of the threads available for the particular process.
The application can two kind of issues to exit, one could be infinite loop and other might be waiting/deadlock (e.g. socket read command is a blocking call). You can easily deduce the problem by attaching to debugger.
Otherwise please provide further information about the threads, code snippet possible.
the application I'm trying to design with Qt is quite data intensive; it is essentially a database. I'm looking for a design that would allow me to keep the UI reactive. My guess is I should keep only the UI in the main thread and create a thread for the database.
However:
- creating a database object inheriting from QThread doesn't seem to be a natural design (what would run() be? )
- I assume I would need to use signals and slots for UI / core interaction; yet this feature seem to be relatively recent in Qt, so I'm wondering if my "design" is wrong.
- QObject descendants are apparently designed to live in the thread in which they were created, so I'm concerned the communication of models (from the database thread) to the UI thread will be problematic.
Thanks for your comments.
You might consider using QtConcurrent::run(). You'll pass in the function you want. It'll spool off a thread to run the function and give you a QFuture that you can use to get the eventual result. You could poll the QFuture to see if it isFinished(). Better, however, may be to use QFutureWatcher which watches the QFuture for you and emits a signal when it's done. See the example code blurb in QFutureWatcher.
Well, I think creating a separate thread for the DB stuff is a good idea... but I would suggest that you only make 1 thread for the DB stuff (not 2, 4, or more). The reason is that unless you are an expert at DB concurrency issues and the locking mechanisms of your DB, things will get complicated.
The thing is that you should not have any other threads mixed with code that has gui or in main of a gui project because any blocking will freeze the GUI as well. So as long as you make a separate DB handler class and thread that, I think you should be OK.
Once I asked that same question "Is this design good?" (after detail explanation), the answer I got is "when doing a design of something, only the sky is the limit".
If you think threads might cause problems, then you should start processes, instead of threads.
Don't forget that you can always block and disable widgets when doing some intensive computation (a famous hourglass icon).
Signals and slots are implementation of observer pattern. In my opinion, it is one of the very useful design patterns. It allows you to easily break dependencies. If you don't like signal slots, then take a look into events.
EDIT
For processes, you can use IPC (inter process communication) - not necessarily using stdout. There are pipes, shared memory and messages.
As for freezing the widgets, you can disable them, or the mouse (turning it into a hourglass) when your application is doing some computation intensive operation, and when you think the GUI might become unresponsive. Or, you can show the invisible widget covering your GUI and change the mouse into the hourglass. This way the mouse events would go to the invisible widget and ignored. You can also add "please wait" box on top of it.
You didn't say what exactly you are trying to achieve. Maybe there is a better way.
I'm using UI threads and I built one thread with message map and it works fine, the problem is when I'm tring to create another thread from the first one.
When I'm getting to this line:
this->PostThreadMessage(WM_MYTHREADMESSAGE,0,0);
I'm getting the next message:
"No symbols are loaded for any call stack frame. The source code cannot be displayed"
I dont know if its could be the reason for the problem but I have built two message maps, one for each thread, I don't know if its ok to do so.
The question is difficult to understand. I'm assuming that you're stepping through your program in the debugger, and you get to that PostThreadMessage line.
If you choose Step Into, the debugger will try to step into the PostThreadMessage call (or the framework wrapper, depending on the type of this). Since PostThreadMessage is a system call, it's likely you don't have symbols for that code. The debugger will just show you disassembly. You can try to use the Microsoft symbol server, but I don't see much point in trying to trace into PostThreadMessage. If the parameters are right, it's going to post the message to the specified thread's queue. Not much to see there.
Posting message to other threads is tricky business. Most Windows programs, even multithreaded ones, typically keep all the UI work to a single thread. It can be done, but there are a lot of caveats and it's usually not worth the pain.
So there are couple of things:
if you want to notify the UI thread from the worker thread, then you should not use PostThreadMessage, here is why.
When this->PostThreadMessage(...) called in a member function of thread A, the message will be sent to thread A, because this points to CWinThread of A. You have to get a pointer to the other thread to post a message to it.
Finally if you want to notify your UI thread, use PostMessage to send a message to the window created by that thread. Add a corresponding handler to the window message map.
Hope this helps