In the MFC Project ,I have main thread focusing on the dialog. another worker thread focusing on receiving data from server ,parsing the data and updating the data into database.
the data from server is quite huge. so I destroy the dialog by clicking the close button while the worker thread is not finished. But the worker thread is not independent. while I delete the object create in the main thread, the worker thread can't continue , that is to say. some error like the access violation problem. (because the worker thread use the member variables in the xxxxdialog class).
the way I create a thread is AfxBeginThread, i use the method waitforsingleobject, still can not work...
I don't want to force to kill the worker thread, otherwise, it will cause memory leak...
You should terminate the workthread safely before the maindlg is destroyed.
Here is the answer [Terminating a thread gracefully not using TerminateThread() ]
Related
I'm writing an application with a button to start/stop a worker thread (which implements QThread).
The worker thread keeps scheduling a job every few milliseconds.
To terminate the worker thread, I'm calling worker.quit() (worker.exit(0) doesn't work either) method from the GUI thread and waiting the finished signal to be fired.
The problem is that even though the finished signal is fired, the thread isn't terminated.
Here is a minimal example:
https://gist.github.com/NawfelBgh/941babdc011f07aa4ab61570d7b88f08
Edit
My interpretation of what happened was wrong: The worker thread was being terminated but the method iter was getting executed in the main thread as said by #sergey-tachenov and as confirmed from the logging generated with the code:
void run() {
std::cout <<"From worker thread: "<<QThread::currentThreadId() << std::endl;
...
void iter() {
std::cout <<"From thread: "<<QThread::currentThreadId() << std::endl;
...
void MainWindow::on_pushButton_clicked()
{
std::cout <<"From main thread: "<<QThread::currentThreadId() << std::endl;
I switched to a different design which doesn't rely on QTimers. But I didn't submit it as an answer since the title of this question is "How to quit the event loop of a worker QThread".
The thread is terminated. Only your timer runs not in the thread you've started but in the main thread, that's why it isn't stopped. This is because it uses queued connections by default and the thread object lives in the thread in which it was created which is the main thread. To fix it:
Do not subclass QThread. It's usually a bad idea unless you want to actually extend QThread's functionality.
Create a separate worker object that inherits QObject.
Use moveToThread to move the worker object to the created thread. It will cause all its slots to fire actually in the thread. If you use default or queued connections, that is.
The QThread docs provide an excellent example on that (the first one).
Note that if you actually want to use data provided by the thread to update GUI, you'll have to somehow correctly publish that data to the GUI thread (possibly using emit and queued connections) instead of trying to update GUI directly from the thread. And if you want to access shared data, you probably need to guard it with a QMutex, not like you do with your shared counter.
I have a List which has data to process. And I have 2 threads,
UI Thread : Updates/Adds the List item,
Thread 1 : Once item added into list it sends the item one by one to another thread 2,
Thread 2 : Does it's work and updates the item accordingly and Once it completes it's work, it checks list and if the corresponding item still exists in the list, If it exists it process the data.
From UI thread when closing the window, I am removing the items from map which are added from the UI. So that the thread 2 won't proceed the items which are removed from list.
And from the UI destruct or, I am deleting the item instances which are added in list.
The issue is, Thread 2 is already processing an item, In the mean time Window is closed and also the destructor deleted the item which is in processing by thread 2.
So the processing of the data by the thread 2 crashes.
I have done this in MFC. How to synchronize these 2 threads (UI deletion and Thread 2). I know there are different Thread synchronization methods in MFC. Which method is best for this scenario?
When you want to halt the operation (perhaps when the user clicks the Close button), first you tell the thread to exit. That can be done with a bool or a event (SetEvent) that the thread checks regularly. After you tell the thread to exit you must not delete the UI or any data being used by thread until you are sure the thread has exited. Use the thread handle in WaitForSingleObject to wait for the thread to exit. WaitForSingleObject suspends the calling thread until the thread handle signals that the thread has exited. Then you can continue the delete and UI shutdown.
How can I create threads in a queue with Qt that execute step by step (when one thread completed another thread started)?
Please give me a code example?
Look at QThreadPool.
However, as Frank pointed out, if you execute things after each other, there is no need for threads.
There is a "finished()" signal from the QThread object. In your thread manager thread (i.e. your main qwidget or qmainwindow), you could have a queue manager class that has a slot to which this signal is connected. The slot would initialize and execute the next thread in the queue when it receives the finished signal from the currently running thread.
This would prevent blocking in your manager thread and allow you to execute these thread objects from a queue as you describe.
Make sure that each time you respond to a finished signal, you connect the next thread's finished signal to your queue manager slot. You also want to make sure that you start the thread in your "add to queue" method if there are no other threads currently running.
If I can't call lock on a mutex in the main application thread (my event handler because you can't lock the main gui thread), how do I share any information between my worker and my main thread?
Just have your worker thread communicate with the main thread through the event handling system. Use AddPendingEvent to send status messages back to the main thread and ProcessEvent to handle the updates.
I have a worker thread in my application, which occasionally recieves information that should be quickly displayed in QML UI. When I have such portion of information, I emit signal, which is received by object that lives on UI thread.
I want this process to be very responsive, so that changes are displayed in QML UI as quickly as possible (this matters because worker thread handles external controller, and I want the shortest "critical path" between user interaction with controller and UI change).
However I discovered, that the time difference between emit signal() and slot called in UI thread is always 20-40 milliseconds. Why so?
What can I do to speed up this? I tried calling QCoreApplication::processEvents() in worker thread after signal is emitted, but this barely changes anything.
Some thoughts:
Can I call processEvents but for UI thread somehow?
Use event with high priority instead of signal. Will it help?
OS: Win8.1, Qt 5.5
When you emit a signal from a worker thread to the UI thread, it is put into the UI event queue, and delivered when the event queue is pumped and reaches that message. If your worker thread is a higher priority than your UI thread, then the UI thread will have to wait until the worker thread blocks. If the worker thread is the same priority it will complete it's time quanta, which may be 20ms. You can make your signal connect Direct rather than Queued, and then you will need to take care of thread safety yourself.