I know very similar questions have been asked before, but I am unable to find an answer for my specific problem. I have a main (GUI) thread which upon button press initializes a worker thread to perform some analysis. I am using signals and slots to communicate between my worker thread and my GUI thread (i.e. when the thread starts and when it finishes), but I need to go deeper than that. My worker thread actually calls another class in a separate implementation file which then iterates through a series of calculations which are sent to std::cout for each iteration (as the code used to be a console application for which I am now writing a GUI). I am trying to feed those outputs for each iteration back into my GUI thread so that my text browser is updated in real time as my code iterates. The problem is, when I emit a signal from the class my worker thread calls, it is not picked up by the GUI thread. I do not get any errors. Does anyone have any suggestions on how to transmit a signal to the GUI from a class that my worker thread is calling? I can post code as required, but I'm not sure what would be most helpful to see and my code is quite extensive (it's an aircraft performance application). Any help would be greatly appreciated. Thank you kindly!
1) Make sure the connect() call for connecting you signal returns true. If it does not, qdebug output usually tells you what is wrong
2) You should use the QueuedConnection type (the default (Auto) should work also)
Related
System / software Details :
Qt Version 4.7.4
Linux
Kernel : 2.6.31 (Custom kernel built for IMX25)
Peripherals :
Graphic LCD (64x128)
Quectel (M 12) GPRS module
Thermal printer
Database : Sqlite3
I am a beginner don't have much experience either in Qt or programming with Linux. I have developed an application where user enter some data manually and that data gets saved in sqlite database. So what I am trying to do is that after certain time lets say 90 seconds data from database should get transferred to the server using the GPRS.
So I am using the Qt's signal and slots mechanism to do the timed data transfer. I have created a slot which gets fired every 90 seconds and as the slot gets fired I am creating/launching a POSIX thread which is suppose to transfer the data to the server.
So what that thread does is it launches the "pppd" and once the "pppd" is up it queries the database for the data and sends the data to the server. And once the data transfer is done I kill the "pppd". The functionality works fine.
But the problem is that the "pppd" takes time to launch so I had to introduce some delay. i.e sleep of 12 seconds is there in order to let the pppd launch successfully. But as the sleep is blocking it makes the main program/thread non responsive until the "pppd" is launched (i.e. it halts/stops all the activities like printing etc.). And as the "pppd" is launched the main thread becomes responsive again.
So please suggest me some solution in order to keep the main thread responsive when "pppd" is launching or please suggest me if there is any other alternative for the same. Also guide me if there's anything wrong with my approach..
Thanks in advance. And I am sorry if I have not followed your standards..
There are several options available to you. It looks like you're using a thread, but then calling sleep in the main thread, which is basically the same as not using thread to do your work at all! You need to leverage Qt processes as illustrated below:
You can use a QProcess in which you start() and use the signal finished() to notify the main thread that it is complete. This is probably what you want to use. All you have to do is:
QProcess *proc = new QProcess;
proc->start("theProcess", QStringList() << "the" << "arguments");
connect(proc, SIGNAL(finished()), this, SLOT(someSlotToUse()));
This sequence of code will start a new process with your arguments, and then call someSlotToUse() when the process is complete.
You can use a QThread along the same pattern.
Basically, what you're trying to do is do the work in another thread, keeping the GUI reactor free to process GUI events rather than long queries. This is a classic problem in Qt and there is a lot of literature out there.
Alternately, you can use a QProcess::concurrent() call, which allows you to run a function in another process, but I've never tested it.
Here are some references for you to look at: Qt Concurrent, QProcess, and QThread
I'm running a long process in the background. I've managed to output the console data to gui. But the problem is that, the data is returned only after the process is finished. But I need to display the data at realtime. ie, I need to display the data, every time it produces some output on the console. I'm running the process with in my gui from a seperate thread.
I mean, it would be like building a gui for the ping command, where output is displayed on console after each packet is send, ie at realtime. I just need to redirect that to gui, in realtime. I'm implementing the gui in wxwidgets. Any help would be greatly appreciated.
Thanking You..
Jvc
Is the output you wish to display generated in a separate process from the process running the GUI? Or in a separate thread in the same process?
I ask because most people, when they ask this question, mean a a separate thread. Since you have tagged your question with "process" I will assume that is what you mean.
You need some inter-process communication. There is a bewildering variety of techniques to do this. Personally, I always use sockets.
wxWidgets has simple, easy to use socket classes wxSocketClient and wxSocketServer.
The background process is probably not running wxWidgets, so you will need something else there. I reccomend boost::asio. I know it looks intimidating, but in fact the tutorial code can be used as is.
There is a lot more to be said, but I risk straying away from the point, since there are so few details in your question.
You can have an output queue protected by a wxMutex. The thread doing the computation writes to the queue, then signals the GUI thread using wxQueueEvent with a custom event to let it know that the thread is not empty. The GUI thread then reads the queue and outputs the data.
Actually i am using this code and works ok, but i 'am wondering if is the correct way.
while WaitForSingleObject(MyThread.Handle, 0) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
The VCL TThread class has its own WaitFor() method that pumps the main message queue internally when called within the main thread context:
MyThread.WaitFor;
ShowMessage('i am done');
Calling Application.ProcessMessages is generally considered a code smell. Let your main thread idle if it's got nothing to do.
If you ran a company and needed one of your workers to run to the store and grab some much-needed supplies, would you then pace by the door until he got back, or would you prefer to sit in your office and rest and wait for him, and find out that the supplies are here because you hear him walk through the door? Either way, he'll take the same amount of time, but the first way's gonna wear your legs out.
Similarly, instead of having your UI watch the thread, have the thread report back to the UI. One way to do this is to have the thread use PostMessage to send a custom message to the form that launched it once it's finished, and put a message handler on the form to respond to it.
It looks correct (if correct means it do the work). What I would change is to wait for a bit more time (50ms looks good to maintain the application responsive) while not eating CPU.
while WaitForSingleObject(MyThread.Handle, 50) = WAIT_TIMEOUT do
Application.ProcessMessages;
ShowMessage('i am done');
Sure there are other ways to do it... <joke>but I usually apply one of the main engineering principles:
if it works, don't touch it!</joke>
I agree with Mason Wheeler's remark, the main thread is best left to do its job, but I would suggest using the OnTerminate event on the thread. It is more 'Delphi natural' and the internal logic does the PostMessage bit for you. Since TThread is not a component, you can't view it in the object inspector and have to write and attach an event handler yourself. It gets called (in the main thread!) after the thread has completed/terminated.
While it looks okay, like jachguate I would use a bigger time-out value than 0 too. If you use WaitForSingleObject(MyThread.Handle, 100) then the main thread will wait a bit longer, thus eating up less CPU cycles.
A better solution would be the use of messages, though. Your application starts the thread and then puts all controls in disabled mode. The thread then executes and when it's finished, use SendMessage or PostMessage to the main window to notify it that the thread is done again. Then your application will just enable every control (and whatever else) again. This has as advantage that you keep the "natural" messageloop for the application alive, instead of running your own messageloop with this solution.Unfortunately, the message-method has one drawback: if the thread crashes then no message will be sent back, so a backup plan would be practical. For example, by adding a timer control to your mainform which checks every second if the thread is still alive. If not, it too would just activate the form again, disabling itself again.
I have a multi-threaded Delphi 6 Pro application that I am currently working on heavily. If I set a breakpoint on any code that runs in the context of the Main thread (VCL thread) I don't have any problems. However, if a breakpoint is triggered on any code in one of my other threads, after I continue the application from the breakpoint, all repaints to the VCL components on the main thread (including the main form) don't happen anymore. The application isn't dead because other background code keeps running, just the main thread. It's as if the windows message dispatcher has been corrupted or rendered dormant.
Note, in this application I allocate my own WndProc() via allocateHwnd() on the main form because I need to catch certain registered messages. From that WndProc() I dispatch any custom messages I handle and if the current message is not handled by my code, I pass the message on by calling the main form's inherited WndProc(). If I do handle the current message I simply return from my WndProc() with Msg.Result set to 1 to tell the dispatcher that the message was handled. I can't simply override the TForm WndProc() instead of allocating my own WndProc() because for some reason the Delphi VCL does not pass through registered messages instantiated with the Windows API RegisterWindowMessage() call.
Has anybody experienced this in similar context and if so, what did you do to fix it?
-- roscherl
Since you call AllocateHWnd, that means you've created another window. You mustn't just take the messages that were addressed to that window and forward them to your form's window. Doing that, you're bound to screw things up in your program, although I'm not sure exactly how. Painting problems sound plausible. You should make sure it's really just painting problems and not that your main thread is still suspended. The debugger should be able to tell you that. (You should call DefWindowProc to make your allocated window handle messages you're not prepared to handle yourself. And returning 1 doesn't tell the dispatcher anything; the dispatcher doesn't care — whoever called SendMessage wants to know the result.)
I promise you that forms are completely capable of receiving registered window messages. Override WndProc or assign a new value to the WindowProc property (and remember to save the old value so you can call it after handling your own messages). The source of your problem lies elsewhere.
UPDATE: I'm not saying the way I got past the problem is a good solution. I need to take Rob Kennedy's notes and do some refactoring. However, to get past the problem for now I gave the thread it's own Window and WndProc() and at the top of the thread Execute loop I have a PeekMessage() while loop with calls to TranslateMessage() and DispatchMessage(). I no longer have a problem with setting breakpoints in the thread, but obviously this compounding of WndProc() methods indicates a structural problem in my code. I wanted to add this reply to fill out the discussion. I'm hoping that once I put Rob's suggestions to work when I clean up my WndProc() methods on the relevant forms, especially the main form, I can get rid of the this new WndProc() that I just added to the thread.
Robert.
I have a worker thread in a class that is owned by a ChildView. (I intend to move this to the Doc eventually.) When the worker thread completes a task I want all the views to be updated. How can I make a call to tell the Doc to issue an UpdateAllViews()? Or is there a better approach?
Thank you.
Added by OP: I am looking for a simple solution. The App is running on a single user, single CPU computer and does not need network (or Internet) access. There is nothing to cause a deadlock.
I think I would like to have the worker thread post (or send) a message to cause the views to update.
Everything I read about threading seems way more complicated than what I need - and, yes, I understand that all those precautions are necessary for applications that are running in multiprocessor, multiuser, client-server systems, etc. But none of those apply in my situation.
I am just stuck at getting the right combination of getting the window handle, posting the message and responding to the message in the right functions and classes to compile and function at all.
UpdateAllViews is not thread-safe, so you need to marshal the call to the main thread.
I suggest you to signal a manual-reset event to mark your thread's completion and check the event's status in a WM_TIMER handler.
suggested reading:
First Aid for the Thread-Impaired:
Using Multiple Threads with MFC
More First Aid for the Thread
Impaired: Cool Ways to Take Advantage
of Multithreading