I'm trying to use threading and semaphore to fix a performance problem in my application.
Problem 1:
The user click on some checkbox. Each time a checkbox is clicked, a somewhat intensive saving is done in the database. The users complaint that is was slow. So now, when they click on the checkbox, I just launch a thread that do the saving (without waiting for the thread to finish). That was ok for a short while.
Problem 2:
When the user is fast and unlucky, sometimes the saving in the database crash because at the same time, the other thread is trying to save in the exact same table. So I think that what we need here is semaphore, but I'm not sure.
What I want is this to happen:
User click on checkbox 1
Launch thread 1
User click on checkbox 2
Launch thread 2 (wait for thread 1 to finish)
thread 1 finish
thread 2 finish
Here is my code:
The function we call to launch the thread
bool SampleSO::ExecuteThreadSauvegarde()
{
//Créer le thread
CWinThread* pThreadSauvegarde = AfxBeginThread(ExecuteThreadSauvegarde, this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
if(pThreadSauvegarde)
{
pThreadSauvegarde->m_bAutoDelete = TRUE;
pThreadSauvegarde->ResumeThread();
}
return true;
}
Then the function who is called by the previous function (static)
UINT SampleSO::ExecuteThreadSauvegarde(LPVOID pParam)
{
SampleSO* pSampleSO = (SampleSO*)pParam;
LONG dwSemCount;
HANDLE hSemaphore = OpenSemaphore( SYNCHRONIZE |SEMAPHORE_MODIFY_STATE, FALSE, _T("Sauvegarde") );
//this is the function that call the saving
pSampleSO->Sauvegarde();
ReleaseSemaphore(hSemaphore, 1, &dwSemCount);
return 1;
}
How can I modify my code so that the critical section is only accessed one thread at the time and that the thread that are waiting for the semaphore go in the critical section as soon as it's released (one at the time).
Thanks!
What you need is not so many threads. Instead, spawn a single worker thread to deal with DB operations. When the user clicks, simply post a message/command via a queue to the worker thread. The worker simply waits for a command, executes it, and goes back to blocking-waiting on the queue. This will require no synchronization beyond thread-safety for the queue itself, which will be trivial because it's single-producer, single-consumer.
Related
If I have a progressbar in the ui thread (window), which shall run endless until a method finishes it's work, will the ui thread block and so the progress bar if I'm waiting for a second QThread to finish? If the ui thread blocks waiting, then i would not to wait for the second thread. I thought to implement a callback method which will be called when the second thread finished, but then: How can i connect to the callback method?
What do I want to do?
I have a window, this window has a progressbar which is first not visible. When the user presses a certain button to request data, a method will be called which returns a RequestPointer which contains a method which returns the request status.
When the user presses the button, i want to make the progress bar visible, running infinitely till the request is finished and i can print the data to the window.
To the Worker i want to pass this pointer and the worker checks in a while (flag) loop, if the status is still running and sleep if so. When the worker finishes, i want to stop the progressbar and make it unvisible again. Do i have to pass the progress bar to the thread, or can i wait for the thread without blocking the ui?
I'm not quite a Qt pro. Really new to it. I tried to get some info from the https://doc.qt.io/Qt-5/qthread.html website, but it's a bit hard for me to understand the code example.
Method in my worker class:
void Worker::watchRequest(RequestPtr r_ptr)
{
bool exit = true;
while (!exit)
{
ErrorCode errorCode = r_ptr->Test();
switch (errorCode)
{
case Request_RUNNING:
QThread::msleep(10);
break;
case Request_ABORTED:
exit = true;
break;
case Request_SUCCESS:
exit = true;
break;
}
}
QThread has a finished signal. Connect this one to some appropriate slot, which will trigger any action necessary on thread completion.
I suppose best candidate to know how far the progress went is the worker thread itself. You might create your own signal that sends the current progress to some slot that will do the update of the progress bar appropriately.
Alternatively, you might use a QTimer to read the current progress from time to time (this resembles closer to what you have now, but does not block the UI).
If you don't want to block the user interface, all you have to do is to call QApplication::processEvents(); in your while-loop.
I have some code which uses std::future instead of QThread and my code looks like this:
while (!progressIndicator->UserBreak()
&& (future.wait_for(std::chrono::seconds(0)) != std::future_status::ready))
{
QApplication::processEvents();
}
This works well.
To update the UI Thread's progress bar while the operation is running, use a QTimer object to increment the progress bar's value (Max value will be :One less than Progress bar's value when the operation completes). Also connect the QThread to a slot by Signal/Slot method to signal the UI thread when the operation has ended. When the QThread finishes the operation, send a signal to a Slot in the UI Thread, which will set the final value of the progress bar and also stop the QTimer.
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.
In my application I have a modal dialog which contains about 20 different combo boxes which are bind to certain fields in the databases. The database is huge and on the loading of dialog I have to load all the combo boxes from the databases. So I setup 20 threads (1 each for every combo box).
Everything works fine, but the problem only occurs when the user closes the dialog with close or cancel button or OK button while the threads are running; in that case the application crashes.
I have tried to terminate the threads prematurely as well but that does not help. Here is the thread termination code
if(m_iNoOfThreadsCompleted != m_iTotalThreads)
{
for(int i = 0; i < m_iTotalThreads - 1; i++)
{
if (m_threads[i] != NULL)
{
GetExitCodeThread(m_threads[i]->m_hThread, &exit_code);
if(exit_code == STILL_ACTIVE)
CloseHandle(m_threads[i]->m_hThread);
}
if(m_iNoOfThreadsCompleted == m_iTotalThreads)
break;
}
}
What is the issue? Or do I need to use a better approach?
Synchronizing threads is generally done using events.
// Before Creating threads
HANDLE hEndEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
// Pass handle to threads
Then on termination
SetEvent(hEndEvent);
WaitForMultipleObjects(m_iTotalThreads,m_threads,TRUE,INFINITE); // Wait for all threads to end
// Loop through and close all the thread handles
Note that you need to be occasionally looking for the end event to be set otherwise your threads won't end.
// In Thread
if (WaitForSingleObject(hEndEvent,0)==WAIT_OBJECT_0) {
// Clean up
return 0;
}
CloseHandle does not terminate the thread. You can call TerminateThread but it's not the nicest thing to do...
What is normal is to provide your threads with a manual-reset event object that signals a shutdown is taking place. Sometimes it's also good to have a flag so that threads can abort lenghty operations. The threads carry on their work as usual, and whenever they have to wait on some object, you include the shutdown event object in that wait.
So the procedure on exit is normally to do this:
Set the shutdown flag
Signal the shutdown event
Resume all threads (in case any are suspended)
WaitForMultipleObjects on all thread handles, with an appropriate timeout
Call TerminateThread on any threads that did not exit within the timeout
Close all thread handles
Destroy the shutdown event
This approach requires that threads are created with _beginthreadex, so that you are responsible for closing the handles. The benefit of this is that you can wait on threads, even after they've exited (of course an exited thread is already in the signaled state).
As an alternative to what paddy describes another approach would be to instead of having 20 threads that load the comboboxes to just have one thread that loads. By having 20 threads you may not be speeding up things anyway depending on your database library.
Then when that thread is loading periodically (like between each checkbox) check whether user pressed cancel or not, if so then stop processing and exit the thread.
This would make the handling less complicated than managing 20 threads IMHO.
I am working on a MFC project where I need a separate loop that will run continually or once every few seconds, and each time it may or may not need to run a Dialog to get some input from the user. I was thinking of using AfxBeginThread, but from what I have read about it, it doesn't really work with a continuous loop.
Don't do it. You can't just rip dialogs off in worker threads. They can only be started in the main thread, because they need the message pump in order to function.
If all you want is a signal of some kind that fires every few seconds, then what you want is a timer. Set the timer for the timer period you want, and when your main thread processed the desired WM_TIMER message, you can pop up a dialog and do your thing.
If you want your worker thread to do some work, which may or may not include asking the user for information, then you'll want to look in to having your thread use PostMessage() to send a message to the main thread, process that message int he main thread by asking the user for data, and then sending a signal back to the worker thread with the input data. One way to accomplish the last bit is by calling QueueUserAPC() from the main thread with the worker thread's handle and a pointer to a function that does somethething with the newly-entered data.
I am working on threading in MFC..I am not sure how to use threading.. I cant attain what i excepted!What I actually tried, is to read the directory and display the file names and at the same time,the progress control should show the progress..I created a dynamic static to display the file names and progress bar control to show the progress...What happens here is,its first displaying all the file names one by one and then after that its showing the progress...so,am bit confused..can anybody explain me how to do that or refer me some articles...if u want i can post the code
This appears to be creating 10 threads for each file
for(int i =0;i<10;i++)
{
THREADINFOSTRUCT *_param = new THREADINFOSTRUCT;
_param->_this = this;
AfxBeginThread(MyThread,_param,THREAD_PRIORITY_ABOVE_NORMAL);
....
}
All 10 threads are simultaneously trying to set a single progress bar. (that's bad)
ts->_this->m_ProgressCtrl.SetRange (0, 500);
while (ts->_this->m_ProgressCtrl.GetPos () < 500)
{
Sleep(250);
ts->_this->m_ProgressCtrl.StepIt ();
}
We don't see the code for creation of the progress bar. But it presumably belongs the the main thread. So when these 10 threads try and SetRange or GetPos or StepIt, they are actually sending messages to the main thread to tell it to do those things.
Meanwhile the main thread is in the do {} }while(FindNextFileW(handle,&findData)); loop, and isn't pumping messages. So those threads all wait until the loop is finished and the main thread goes back to its message pump.
Then each of your threads wakes up and returns from calling SetRange, etc. But one at a time, since only message at a time can be processed by the main thread.
For this to work, you need to move the FindNextFile loop into a thread, and you need to let the main thread go back to the pump so that the UI can be updated while things progress.
You also need to stop trying to set the progress bar directly from any of your non-main threads. Instead use PostMessage to post messages back to the main thread and let it set the progress bar. That way your threads don't end up blocking and waiting for the main thread to talk to the progress bar on their behalf.