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.
Related
I've got the following scenario: An Application B is supposed to start an application A and then to wait for A becoming idle. For this purpose, B uses CreateProcess in combination with WaitForInputIdle, and unfortunately the timeout of this command has been set to INFINITE.
This is the corresponding part of B's source code:
void StartA(void){
STARTUPINFO siInfo;
PROCESS_INFORMATION piInfo;
ZeroMemory(&siInfo, sizeof(siInfo));
ZeroMemory(&piInfo, sizeof(piInfo));
CreateProcess(L"A.exe", L"", 0, 0,
false, CREATE_DEFAULT_ERROR_MODE, 0, 0,
&siInfo, &piInfo);
WaitForInputIdle(piInfo.hProcess, INFINITE); // A will block this command!
CloseHandle(piInfo.hProcess);
CloseHandle(piInfo.hThread);
}
When I call my application A from this application B, B will be blocked by its WaitForInputIdle command forever due to the SendMessage command invoked by A's TestThread. If I create the TestThread only after the FormShow event, then WaitForInputIdle will return as expected. That's a solution and though I'm aware of the article WaitForInputIdle waits for any thread, which might not be the thread you care about, I like to understand what actually happens here.
This is the simplified source code of application A. It just consists out of a TForm and the class TestThread, which is derived from TThread.
class TestThread : public TThread {
public:
__fastcall TestThread(HWND in_msg) : msg(in_msg), TThread(false) {};
virtual __fastcall ~TestThread(){};
private:
void __fastcall Execute(){
// Next line leads to WaitForInputIdle blocking
SendMessage(msg, WM_USER, NULL, NULL);
while(!Terminated) Sleep(1);
}
HWND msg;
};
class TFormA : public TForm{
private:
TestThread * testthread_p;
public:
__fastcall TFormA(TComponent* Owner){
testthread_p = new TestThread(Handle);
}
virtual __fastcall ~TFormA(){}
};
Why does the command WaitForInputIdle fail to detect the idle state of application A?
The launched app never has a chance to enter an "input idle" state.
Assuming TFormA is the app's MainForm, it gets created at app startup, and thus creates the thread, before the VCL's main UI message loop starts running (when Application->Run() is called by WinMain()).
Even though the worker thread is using SendMessage() and not PostMessage(), it is sending messages across thread boundaries, so each message is not dispatched to the window until the receiving thread (in this case, the main UI thread) calls (Peek|Get)Message(). This is stated in the SendMessage() documentation:
Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message.
By the time the main UI message loop starts running, one message from the thread has already been sent to the window and is waiting to be dispatched. Subsequent messages are being sent with a 1ms delay between them. So, the first time the main UI message loop attempts to retrieve a message from the queue, there is already a message waiting. By the time the loop dispatches that message for processing and goes back to the queue to wait for a message, there is already a new message waiting for it.
The WaitForInputIdle() documentation says:
The WaitForInputIdle function enables a thread to suspend its execution until the specified process has finished its initialization and is waiting for user input with no input pending. If the process has multiple threads, the WaitForInputIdle function returns as soon as any thread becomes idle.
The main UI thread has continuous messages pending from the thread, so it can't become "input idle". And the worker thread does not retrieve inbound messages of its own, so it can't become "input idle", either (see WaitForInputIdle waits for any thread, which might not be the thread you care about).
Thus, the app process as a whole never becomes "input idle", so WaitForInputIdle() blocks until its timeout elapses, which in this case is INFINITE, so it blocks indefinately.
The Form's OnShow event is not fired until well after the main UI message loop is running and has already processed several other window messages, so the app has time to go "input idle", unblocking WaitForInputIdle(), before the thread gets created and starts sending messages to the window.
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.
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.
I use an application that uses mdi and a script can be attached to, and detached from, a mdi window to be run/stopped on demand; this script loads my dll that does some work; it does fine so; however, when I detach the script still all is fine and the application should unload the dll (and it calls dllmain with the appropriate thread_attach/detach and process_attach/detach operations). Now if I try to re-attach the script to the winow, or to attach it to another window, after the dll has been in use once - the main application crashes. I have isloated the problem to a thread that is created by the dll; the tread crates a window; so, I create the thread like so:
if (!hThread) hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
and, when the script is detached it shuts down the thread like so (no matter if the commented-out lines are uncommented-out):
SendMessage(hWnd, WM_DESTROY, 0, 0);
//TerminateThread(hThread, 0);
//WaitForSingleObject(hWndThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;
I'm at a loss here as to why the main app crashes. A different thread (i.e. one that would simply sleep for a second and loop, will do no harm. What gives?
Ok, here are some ideas:
You said your thread opens a window. Do you run a message loop in the thread function, or you expect your window to be serviced by some other message loop?
If you are running your own message loop in the thread, then exiting the loop may or may not happen, depending on how you have written it. If you use something like:
while(GetMessage(&msg, ...) // msg loop in the thread function
{
....
}
DestroyWindow(hWnd); // see comment below
then this requires a WM_QUIT and not WM_DESTROY to exit. Anyway, the best is to send your window a WM_QUIT and after exiting the message loop then call DestroyWindow() to destroy it properly.
Quoting from MSDN:
DestroyWindow function
Destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus from it. The function also destroys the window's menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain
After posting WM_QUIT message to your window, your main thread should wait for the window thread to exit. Here is some relevant code:
SendMessage(hWnd, WM_QUIT, 0, 0); // send your quit message to exit the msg loop
if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) // wait up to 5 seconds
{
TerminateThread(hThread, -1); // bad! try to never end here
}
I hope this helps. I use this in a threaded log viewer that uses a window to display log messages.
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.