This topic is 3625 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

// CTestDlg.h
//...
public:
CListBox m_ListBox;
//...

// CTestDlg.cpp
BOOL CTestDlg::OnInitDialog()
{
//...

}
{
}

// ThreadObject.h

{
public:

private:
CListBox*       m_pListBox;
};


// ThreadObject.cpp
#include "stdafx.h"

// Constructor
m_pListBox(pListBox)
{
}
// Destructor
{

}

{
return 0;
}
{
{
Sleep(1000);
m_pListBox->InsertString(0, L"Tick");
}
}

When I start this up and run, "Tick" gets inserted to the list box about every 1 second as expected. No problem. But when I click the Kill Thread button which deletes the pointer to the ThreadObject and ~ThreadObject gets called, bad things happen. m_bThreadRun is set to false and the thread seems to exit just fine, but I never return from the WaitForSingleObject() call and I don't know why.

Share on other sites
Quote:
What if you take MFC out of the picture and never have the thread do anything but Sleep(1000)? Does WaitForSingleObject() return then? Are you verifying this with breakpoints and the debugger?

Share on other sites
Quote:
 Original post by Evil SteveWhat if you take MFC out of the picture and never have the thread do anything but Sleep(1000)? Does WaitForSingleObject() return then? Are you verifying this with breakpoints and the debugger?

If I do nothing but comment out the call to InsertString() using pListBox from the ThreadObject thread, WaitForSingleObject() returns with no problems. The output window shows "The thread 'Win32 Thread' (0xc24) has exited with code 0 (0x0).", verifying that the thread has stopped. If I keep the call to InsertString() in, the thread never exits because it never returns from WaitForSingleObject().

Share on other sites
Quote:
Original post by Mantear
Quote:
 Original post by Evil SteveWhat if you take MFC out of the picture and never have the thread do anything but Sleep(1000)? Does WaitForSingleObject() return then? Are you verifying this with breakpoints and the debugger?

If I do nothing but comment out the call to InsertString() using pListBox from the ThreadObject thread, WaitForSingleObject() returns with no problems. The output window shows "The thread 'Win32 Thread' (0xc24) has exited with code 0 (0x0).", verifying that the thread has stopped. If I keep the call to InsertString() in, the thread never exits because it never returns from WaitForSingleObject().
That does it without touching MFC (Apart from getting the HWND from the CListBox).

That's about as far as my MFC knowledge goes unfortunately...

Share on other sites
Quote:
 Original post by Evil SteveOk, how about using this instead:SendMessage(m_ListBox, LB_ADDSTRING, 0, (LPARAM)L"Tick");That does it without touching MFC (Apart from getting the HWND from the CListBox).That's about as far as my MFC knowledge goes unfortunately...

Using that method, the "Tick" messages still get to the List Box, but the thread still hangs. :(

Share on other sites
Quote:
 A thread that uses a wait function with no time-out interval may cause the system to become deadlocked. Two examples of code that indirectly creates windows are DDE and the CoInitialize function. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject.

WaitForSingleObject.

Share on other sites
When it's frozen, in the debugger select break all from the debug menu. Also turn on the threads window (Debug->Windows->Threads) so you can switch between threads easily.

From there you should be able to see what each thread is up to in the debugger and step through them if they are still running, which should help you find out why the thread isn't stopping.

However in this case reading the documentation for SendMessage() might be a good plan. Most notably SendMessage blocks until the receiving thread has processed the message, however in your case the receiving thread will be waiting for the sending thread to exit, and therefore won't be processing messages. That means you'll be deadlocked.

The way round that is to find another way of getting the message to the main thread. PostMessage() for example.

Share on other sites
Antheus's quote/link on the danger of WaitForSingleObject() describes the problem, I believe. I'm deleteing the ThreadObject from the main UI thread. This causes the main UI thread to Wait on the completion of my created thread. But the main UI thread needs to handle all messages coming to the window, which it can't do if it's waiting for WaitForSingleObject to return, which seems to cause the deadlock. Somewhere in the process of WaitForSingleObject(), the window (UI thread) must need to access some message(s) for it to work.

Now, the big question is, how do I get around this? The link recommends using MsgWaitForMultipleObjects<Ex>, but I'm not sure how that works. I've read the documentation and played with it a bit, but I'm still missing something. It's either not waiting for the thread to finish or still dead-locks.

Share on other sites
The probable cause is an optimization the compiler does. Since you don't access m_bThreadRun in your thread function the compiler optimizes the check away.

AFAIK there's no deadlock if a SendMessage call calls another SendMessage inside the WindowProc.

Share on other sites
Quote:
 Original post by MantearNow, the big question is, how do I get around this? The link recommends using MsgWaitForMultipleObjects, but I'm not sure how that works. I've read the documentation and played with it a bit, but I'm still missing something. It's either not waiting for the thread to finish or still dead-locks.
From what I understand, it's because adding to the list box causes the SendMessage() call. Messages are always processed by the thread that owns it, so it tries to get the main thread to process the message - but it's stalled in WaitForSingleObject().
I bet that if you move the Sleep() to after InsertString(), the bug will go away 99% of the time, since it'll be very unlikely you'll change the bool and enter WaitForSingleObject() between the while() condition and the InsertString() call. Note that this isn't a fix, it just shows if this is the likely cause (And using this as a fix will come back to haunt you later on).

Quote:
 Original post by EndurionThe probable cause is an optimization the compiler does. Since you don't access m_bThreadRun in your thread function the compiler optimizes the check away.Try marking m_bThreadRun with volatile.AFAIK there's no deadlock if a SendMessage call calls another SendMessage inside the WindowProc.

1. 1
2. 2
3. 3
Rutin
23
4. 4
5. 5
khawk
14

• 9
• 11
• 11
• 23
• 10
• Forum Statistics

• Total Topics
633653
• Total Posts
3013153
×