Newbie to embedded systems here. I have to synchronize two threads with events. My code show only "Show in edit box 2sec" and is not going to secondthread to show what I have there. I should show in an edit box for 2 seconds with one thread a message and after two seconds i should show for 3 seconds another message. This should be repeat forever.
void FirstThread(void)
{
int i;
//write data to edit box
CString szEdit;
szEdit.Format(_T("Show in edit box 2sec"));
m_editbox->SetWindowText(szEdit);
while(1){
WaitForSingleObject (hEvent, INFINITE);
for(i=0;i<1;i++){
Sleep(2000);
}
SetEvent (hEvent);
}
}
void SecondThread (void)
{
int i;
//write data to edit box
CString szEdit;
szEdit.Format(_T("Show in edit box 3 sec"));
m_editbox->SetWindowText(szEdit);
while(1){
WaitForSingleObject (hEvent, INFINITE);
for(i=0;i<1;i++){
Sleep(3000);
}
SetEvent (hEvent);
}
}
You should use two different events, one signaling the end of sleeping in the first thread, the other one - in the second thread. (Initially, one of these events should be set (signaled), the other - unset.)
There are problems with your approach. MFC will not permit you to access a control from a thread that did not create it, and placing WaitForSingleObject or Sleep within the main thread stops it from processing messages so the program becomes "unresponsive".
You could do this with no threads, no WaitForSingleObject, no Sleep and no events by using a timer in the main thread. The main thread would initially call SetTimer, then process the WM_TIMER message to change the control text periodically. Meanwhile, the program would be able to process any other messages normally, between the WM_TIMER messages.
Related
Basically exactly what the title says. I would like to update the text that a button contains every 1 second when the user presses that particular button. I have noted that when the program doesn't have focus it works alright and the text refreshes correctly but when I am hovering over the program or when I am trying to click on it's menu Windows inform me that the program is unresponsive and asks me if I want it terminated. When the loop finishes the program returns to its normal state. Also any action I might have done (like moving it around or closing it) while it was Sleep()-ing is executed after the loop. Here is a bit of code:
case ID_BUTTON_START:
// Code executed when pressing Start Button.
char startButtonText[30]; // Storing next loop text
for (int i=5; i>0; i--)
{
sprintf(startButtonText, "Starting in ... %d", i);
SendMessage(hwndButtonStart, WM_SETTEXT, 0, (LPARAM)(startButtonText));
Sleep(1000);
}
Is this normal? If not what's causing this?
The WndProc does not process messages asynchronously within an application which means all messages are expected to be handled quickly and a return value delivered immediately. You must not Sleep in the UI thread since it will block other UI events from being processed. Any heavy work or synchronous requests/jobs which are likely to take a long time should be performed in worker threads. There are at least three viable options:
Create a new (worker thread) for the task.
If the task is likely to be done often, use a thread pool instead.
Set and subscribe to timer events.
I think the call to Sleep() might be keeping you from returning from the WndProc, so your application is not processing the incomming events for 5 secs. I suggest you try to subscribe to 5 timer events in 1s, 2s,..., 5s. Like when the timer message is recieved the button text must change. I don't know a way how to do that off the top of my head.
Basically exactly what the title says. I would like to update the text that a button contains every 1 second when the user presses that particular button. I have noted that when the program doesn't have focus it works alright and the text refreshes correctly but when I am hovering over the program or when I am trying to click on it's menu Windows inform me that the program is unresponsive and asks me if I want it terminated. When the loop finishes the program returns to its normal state. Also any action I might have done (like moving it around or closing it) while it was Sleep()-ing is executed after the loop. Here is a bit of code:
case ID_BUTTON_START:
// Code executed when pressing Start Button.
char startButtonText[30]; // Storing next loop text
for (int i=5; i>0; i--)
{
sprintf(startButtonText, "Starting in ... %d", i);
SendMessage(hwndButtonStart, WM_SETTEXT, 0, (LPARAM)(startButtonText));
Sleep(1000);
}
Is this normal? If not what's causing this?
The WndProc does not process messages asynchronously within an application which means all messages are expected to be handled quickly and a return value delivered immediately. You must not Sleep in the UI thread since it will block other UI events from being processed. Any heavy work or synchronous requests/jobs which are likely to take a long time should be performed in worker threads. There are at least three viable options:
Create a new (worker thread) for the task.
If the task is likely to be done often, use a thread pool instead.
Set and subscribe to timer events.
I think the call to Sleep() might be keeping you from returning from the WndProc, so your application is not processing the incomming events for 5 secs. I suggest you try to subscribe to 5 timer events in 1s, 2s,..., 5s. Like when the timer message is recieved the button text must change. I don't know a way how to do that off the top of my head.
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.
In one C++ application I have a window whose message loop runs in a separate thread because the main thread is busy calculating and rendering a simulation. The window acts as a log window for the simulation. When the simulation throws an exception, the simulation closes and the log window displays the details.
Now the main thread should wait until the log window is closed. Since the message loop runs on a separate thread, I tried to
WaitForSingleObject(logwindow->thread, INFINITE);
from the main thread.
However, this seems to block the message pump and the log window freezes. So how do I correctly wait until a window is closed or a thread ends?
ED: The window is created on the main thread but runs on a different thread. I'll go ahead and change it so it creates on the message loop thread too.
You have a few options.
Run all the UI out of the main thread and get the worker thread to synchronize reporting back to the main thread to display, for example via PostMessage or SendMessage.
Don't wait at all and get the worker thread to post a message to the main thread when the worker is done.
Use MsgWaitForMultipleObjects for your wait.
To elaborate on MsgWaitForMultipleObjects, it's a wait function that can be configured to return when messages arrive in the queue. Thus you can keep your message pump alive whilst also using a blocking wait in between processing queued messages.
In pseudo-code you would write it like this:
do
{
WaitResult = MsgWaitForMultipleObjects(1, hThread, TRUE, INFINITE, QS_ALLEVENTS);
if (WaitResult == MessageArrivedOnQueue)
PumpMessageQueue();
} while (WaitResult != WaitHandlesSignaled)
The fact that the log window is freezing while the main thread is in a blocking wait suggests the worker thread is sending a message to the main thread and then waiting for a reply, but the main thread is already blocked and cannot reply to it. That is a classic deadlock situation for both threads. You should use MsgWaitForMultipleObjects() instead of WaitForSingleObject() in the main thread to detect when new messages need processing while waiting, eg:
do
{
DWORD dwRet = MsgWaitForMultipleObjects(1, &(logwindow->thread), FALSE, INFINITE, QS_ALLINPUT);
if (dwRet == 0xFFFFFFFF) break;
if (dwRet == (WAIT_OBJECT_0 + 1))
{
process messages here...
}
}
while (dwRet != WAIT_OBJECT_0);
I agree with David that you really should be doing all UI work in the main thread and do your calculations in the worker thread, not the other way around.
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.