Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

why UI gets hangs

323 views
Skip to first unread message

Aditya

unread,
Mar 21, 2008, 9:29:15 AM3/21/08
to
I have a simple MFC app with a dialog. from the initinstance of the
App i am doing dlg.DoModal().

In the dialog i have a button. when i click the button the thread
gets run in a for loop for 1 min...

but in between this 1 min if i try to do some operation or post
message to the queue from another thread then UI shows hangs but
why...even the thread busy and not processing msg it should not
hang..because after 1 min it will process the msg from message queue..

pls let me know ur suggestion

Thanks in adv
Aditya

Tom Serface

unread,
Mar 21, 2008, 9:34:04 AM3/21/08
to
A few questions: Have you already created a mainframe before popping up a
dialog? Is there any way you could run the dialog as a nonmodal and just
close it down using a timer or something like that. Also, if your thread is
not constantly processing messages you may want to have it sleep for a few
milliseconds between loops just to yield some time.

Tom

"Aditya" <adity...@gmail.com> wrote in message
news:93474346-22d9-4568...@d21g2000prf.googlegroups.com...

David Ching

unread,
Mar 21, 2008, 9:45:24 AM3/21/08
to
"Aditya" <adity...@gmail.com> wrote in message
news:93474346-22d9-4568...@d21g2000prf.googlegroups.com...

Please show the code that executes when the button is clicked. What do you
mean "the thread gets run in a for loop for 1 min"? If it's in a loop, the
primary thread will of course not respond to posted messages since it's in
the loop!

-- David


Aditya

unread,
Mar 21, 2008, 10:02:39 AM3/21/08
to
On Mar 21, 6:45 pm, "David Ching" <d...@remove-this.dcsoft.com> wrote:
> "Aditya" <adityabo...@gmail.com> wrote in message

Hi David
void CtempDlg::OnBnClickedButton1()
{

for(;;)
{
::Sleep(60000);
break;
}
}

during this 1 min if i do some major operation on the UI then its
hangs..also if i move some another window on top of it becomes hang..

Thanks

Nick Meyer

unread,
Mar 21, 2008, 10:11:46 AM3/21/08
to Aditya
Aditya wrote:

> void CtempDlg::OnBnClickedButton1()
> {
>
> for(;;)
> {
> ::Sleep(60000);
> break;
> }
> }

As David pointed out, if this is the main thread, you are literally
suspending execution of the whole thread (including the main message
loop that provides for GUI responsiveness) for the whole minute. Not to
mention that this loop is silly; it's functionally equivalent to the
single ::Sleep statement.

What exactly is it you're trying to do?

Nick

Aditya

unread,
Mar 21, 2008, 10:23:32 AM3/21/08
to

Hi Nick,
you r correct. i just trying to simulate some long operation using
sleep(60000) and within that period if some other thread post
messages to this thread message queue or do some ui operation then UI
hangs...i want to know why it hangs..

Tom Serface

unread,
Mar 21, 2008, 10:21:07 AM3/21/08
to
Hi Aditya,

You may want to try something like this:

http://visualcpp.net/index.php?qID=49

If you need to wait for the thread to complete before continuing in your
dialog.

Tom

"Aditya" <adity...@gmail.com> wrote in message

news:a54e0745-9119-4248...@u10g2000prn.googlegroups.com...

Aditya

unread,
Mar 21, 2008, 10:38:28 AM3/21/08
to
On Mar 21, 7:21 pm, "Tom Serface" <tom.nos...@camaswood.com> wrote:
> Hi Aditya,
>
> You may want to try something like this:
>
> http://visualcpp.net/index.php?qID=49
>
> If you need to wait for the thread to complete before continuing in your
> dialog.
>
> Tom
>

Hi Tom,
I know this way i can slove the problem..but i want to know some
other things...
when my primary UI thread doing some time consuming operation and in
that period if i do some UI operation from another thread or drag the
UI itself
it gets hang...why it hangs...i know that the primary UI thred blocked
and can't process the messages queue but it can process the things
after finish the work..

in summary..all people try to keep the primary UI thred free to
process messages and thats why all major operation use to do in work
thread...but my question is what is the main reason of keeping UI
thread free

David Wilkinson

unread,
Mar 21, 2008, 11:00:17 AM3/21/08
to

Aditya:

It hangs because you are deliberately hanging it by calling Sleep() in the main
thread. Never do this! The main purpose of a secondary thread (at least on a
single CPU machine) is to keep the GUI alive.

--
David Wilkinson
Visual C++ MVP

David Wilkinson

unread,
Mar 21, 2008, 11:03:18 AM3/21/08
to
Aditya wrote:
> Hi Tom,
> I know this way i can slove the problem..but i want to know some
> other things...
> when my primary UI thread doing some time consuming operation and in
> that period if i do some UI operation from another thread or drag the
> UI itself
> it gets hang...why it hangs...i know that the primary UI thred blocked
> and can't process the messages queue but it can process the things
> after finish the work..
>
> in summary..all people try to keep the primary UI thred free to
> process messages and thats why all major operation use to do in work
> thread...but my question is what is the main reason of keeping UI
> thread free

Aditya:

That is the main reason to keep the primary UI free: to process messages.
Messages from other threads, or messages caused by user actions.

I'm not quite sure what is confusing you.

Aditya

unread,
Mar 21, 2008, 12:10:08 PM3/21/08
to

hi David,
ya u r correct ..we need to keep the primary thread free to process
messages,
messages from other threads or messages caused by user actions but my
question is if i block
it and during that period did some UI operation from other
threads..why UI get hangs...is there any reason special reason like
need
to process the message immediately

Aditya

unread,
Mar 21, 2008, 12:12:05 PM3/21/08
to

yes..myself hanged it..but my question is why it hangs..what is the
internal..

Giovanni Dicanio

unread,
Mar 21, 2008, 12:27:08 PM3/21/08
to

"Aditya" <adity...@gmail.com> ha scritto nel messaggio
news:e77e8622-9295-45c2...@i12g2000prf.googlegroups.com...

> but my
> question is if i block
> it and during that period did some UI operation from other
> threads..why UI get hangs...is there any reason special reason like
> need
> to process the message immediately

When your app starts, Windows calls a function whose name is "WinMain".

If you want to write a WinMain implementation, you will do some
initialization like creating a window, etc.
And you would also code what is called a "message pump". That is a loop
something like this:

<code>

...

//
// Message-pump (inside WinMain)
//

BOOL bRet;

while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

// App terminates - return to Windows
return msg.wParam;

</code>


The message pump takes messages from the message queue (if any) and
dispatches them to the window procedure.
You specify a pointer to a function (which is the window procedure) when
registering window class.
The window procedure typically implements a very big switch statement, to
process the messages Windows sends to your window, e.g.

<code>

//
// Window procedure: process messages sent to our window
//
LRESULT CALLBACK WindowProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM
lParam)
{
...
switch (iMsg)
{
case WM_CREATE:
....

case WM_PAINT:
...

case WM_SETFOCUS:
...

case WM_SIZE:
....

case WM_DESTROY:
...

...etc. ...
}

// Default processing by Windows
return DefWindowProc(hWnd,iMsg,wParam,lParam);
}

</code>

MFC hides all that behind the scene.
But if you write Win32 applications (without the help of MFC), you have to
write that kind of code and understand all that.

If you have a lengthy operation, you are not returning to Windows soon, so
the message-loop (in WinMain) is waiting for you to finish process your
message.
Messages like WM_PAINT (important to e.g. redraw the GUI), WM_SIZE, etc. are
not processed, because you are busy in your lengthy operation, and you don't
return soon to Windows. So the message-loop in WinMain is blocked, messages
sent by Windows accumulate in the message queue, and you are not processing
them.

This is why worker threads are useful: the main GUI thread can process the
message queue continuously (so the GUI can react to e.g. user's input), and
the worker thread can do its lengthy job in the background, without blocking
the message-pump loop.

HTH,
Giovanni


David Wilkinson

unread,
Mar 21, 2008, 12:43:01 PM3/21/08
to
Aditya wrote:
>> That is the main reason to keep the primary UI free: to process messages.
>> Messages from other threads, or messages caused by user actions.
>>
>> I'm not quite sure what is confusing you.
>>
>> --
>> David Wilkinson
>> Visual C++ MVP
>
> hi David,
> ya u r correct ..we need to keep the primary thread free to process
> messages,
> messages from other threads or messages caused by user actions but my
> question is if i block
> it and during that period did some UI operation from other
> threads..why UI get hangs...is there any reason special reason like
> need
> to process the message immediately

Aditya:

It is a design mistake to try to alter the GUI directly from a secondary thread.
Apart from anything else, most GUI functions use SendMessage() internally, and
if the windows were created in the main thread and you block that thread, the
messages will not be delivered. Perhaps this is the answer you were looking for?

In MFC there are additional reasons not to access GUI components from secondary
threads; in particular the map from HWND's to CWnd's is maintained on a per
thread basis.

All these problems can be avoided by these simple rules:

1. Never block the main thread.

2. Never create GUI components in secondary threads.

3. Always have secondary threads use PostMessage() (or SendMessage() if you are
careful) to transmit information to the main thread, so the main thread can
update the GUI.

Aditya

unread,
Mar 21, 2008, 12:53:13 PM3/21/08
to
On Mar 21, 9:27 pm, "Giovanni Dicanio" <giovanni.dica...@invalid.com>
wrote:
> "Aditya" <adityabo...@gmail.com> ha scritto nel messaggionews:e77e8622-9295-45c2...@i12g2000prf.googlegroups.com...

Hi Giovanni,

ya its alright...even u can see dllgcore.cpp, wincore.cpp files for
these things and winproc fun is
AfxWndProcBase for MFC (provided by windows when registering) gets
called from OS
but my confusion is i am not processing the messages(WM_PAINT,
WM_SIZE...) for some period of time
and UI gets hangs...is it only because message queue gets full or any
other reason..
do u have any doc which saying if message queue gets full or not
processing messages like (WM_PAINT, WM_SIZE..) ui may gets hangs

Aditya

Tom Serface

unread,
Mar 21, 2008, 12:59:36 PM3/21/08
to
Hi Aditya,

Yes. You should only have one UI thread and that thread should be left free
to process messages (I.E., don't ever block it). You can communicate to the
UI thread using SendMessage or PostMessage (I tend to use PostMessage) as
others have mentioned. It's a little confusing, but once you get it set up
I think you'll find it easy enough. I typically have a set routine called
setUIWnd(CWnd *pWnd) in my thread code and set the UI window with something
like:

void CMyThread::setUIWnd(CWnd *pWnd)
{
m_pUIWnd = pWnd;
}

m_MyThread.setUIWnd(AfxGetMainWnd()); // When called from GUI thread before
starting worker thread.

Then in the worker thread you can post messages to this window:

if(m_pUIWnd != null)
m_pUIWnd.PostMessage(WM_MYMESSAGE,...);

Then in your UI window handle the message with a typical handler:

ON_MESSAGE(WM_UPDATE_SERVER_STATE, OnServerStateChange)

LRESULT CMainFrame::OnServerStateChange(WPARAM wParam, LPARAM lParam)
{
// Do whatever
return 0L;
}

That way your worker thread can communicate (progress, states, whatever)
with your UI thread without blocking the UI thread. If you need to stop a
window from operating you can disable it as well using EnableWindow(false),
but that won't block the UI.

Tom

"Aditya" <adity...@gmail.com> wrote in message

news:a73195f9-433a-4911...@i7g2000prf.googlegroups.com...

Tom Serface

unread,
Mar 21, 2008, 1:02:03 PM3/21/08
to
I can't say for sure, but I'd guess the message queue is only getting full
because you are stopping the main thread from processing messages. I don't
know why that would hang it, but perhaps the OS puts it into a "Not
Responding" mode when the message queue is full. In any case you can easily
fix it using the advice given here in this thread.

Tom

"Aditya" <adity...@gmail.com> wrote in message

news:303513a5-6250-4376...@s8g2000prg.googlegroups.com...

Aditya

unread,
Mar 21, 2008, 1:06:48 PM3/21/08
to

hi david,
these are the simple rules people follow to avoid UI hanging problem.
i am putting the steps below..
1) main GUI thread is busy..
2) during main thread busy i am doing some more click or draging the
UI
3) OS puts the message in the message queue for steps 2 and messages
not picking up by GUI main thread
r u meaning OS doing sendmessage() and since if the GUI thread not
releasing the OS call it gets hangs??
but i think OS put the messages in the queue and leave it to the GUI
thread to process.

i am not clear in that level what happens in step 3 which makes the UI
hangs..

Aditya

Giovanni Dicanio

unread,
Mar 21, 2008, 1:02:10 PM3/21/08
to

"Aditya" <adity...@gmail.com> ha scritto nel messaggio
news:303513a5-6250-4376...@s8g2000prg.googlegroups.com...

Hi,

> but my confusion is i am not processing the messages(WM_PAINT,
> WM_SIZE...) for some period of time
> and UI gets hangs...is it only because message queue gets full or any
> other reason..

The UI gets hang because those messages (like WM_PAINT) are not processed.

For example, if Windows needs to redraw your window, it sends your app a
WM_PAINT message. But if you don't process that message, your window will be
in "waiting for repainting" state for long time (until your message pump has
a chance to get WM_PAINT from message queue, and process it in window
procedure).

Giovanni


David Ching

unread,
Mar 21, 2008, 1:11:55 PM3/21/08
to

"Aditya" <adity...@gmail.com> wrote in message
news:e77e8622-9295-45c2...@i12g2000prf.googlegroups.com...

> ya u r correct ..we need to keep the primary thread free to process
> messages,
> messages from other threads or messages caused by user actions but my
> question is if i block
> it and during that period did some UI operation from other
> threads..why UI get hangs...is there any reason special reason like
> need
> to process the message immediately

Perhaps you need to show the exact code you're talking about. It's not
clear what you mean by "UI operation from other threads." Only the primary
thread should do UI operations. Anything that takes a long time should be
on another thread. And the primary thread should not be looping or sleeping
while the other thread is working, or else it won't process messages and
hang.

-- David


David Ching

unread,
Mar 21, 2008, 1:13:59 PM3/21/08
to

"Aditya" <adity...@gmail.com> wrote in message
news:271a11d5-87ed-460a...@i12g2000prf.googlegroups.com...

#1 should never happen. The GUI thread should never be busy. Otherwise it
won't process the messages in step #3 caused by user interaction in step #2.
So fix #1.

-- David


David Wilkinson

unread,
Mar 21, 2008, 1:17:53 PM3/21/08
to
Aditya wrote:
> 1) main GUI thread is busy..
> 2) during main thread busy i am doing some more click or draging the
> UI
> 3) OS puts the message in the message queue for steps 2 and messages
> not picking up by GUI main thread
> r u meaning OS doing sendmessage() and since if the GUI thread not
> releasing the OS call it gets hangs??
> but i think OS put the messages in the queue and leave it to the GUI
> thread to process.
>
> i am not clear in that level what happens in step 3 which makes the UI
> hangs..

Aditya:

Step 1 is your problem. The main thread should never be busy doing real work,
and it should never Sleep for an extended time. If the main thread is busy or
sleeping, it cannot process massages, either from other threads or from user action.

You do not use a secondary thread *because* the main thread is busy, but rather
in order to make sure that it is *not* busy.

Nick Meyer

unread,
Mar 21, 2008, 1:20:41 PM3/21/08
to

Your main thread has a message loop. I think it's in the
CWinApp-derived class. There's also a modal dialog loop in your
CDialog-derived class. You put the main thread to sleep, so it can not,
under any circumstances, run for 1 minute. When the other threads post
messages to this window's or thread's queue, they sit there until this
thread wakes up, because in order to process messages, it has to
execute, but it can't execute because it's sleeping.

The point of having a second thread in the first place is to do the
lengthy operations in the second thread so the main thread can continue
to respond to user actions. You should be doing your lengthy operation
in the second thread, which doesn't need to be responding to messages.

Nick

Tom Serface

unread,
Mar 21, 2008, 1:33:14 PM3/21/08
to
I think this may be the biggest confusion. I know I still get caught by
this at times. It is so easy to put in something like AfxMessageBox() into
the worker thread and that just gets me (and I assume others) into trouble.
It works sometimes, but... I've also been caught when I tried to do that
sort of thing (UI) from a callback from a DLL function (like a message
server listener) which may (even though I don't know it) be running on its
own thread. My personal opinion these days is when in doubt send a message
to the UI thread. I also never call functions direction in dialogs or views
(except through UpdateAllViews()). This is a tough thing to get used to
since it's so easy to just grab a view pointer and call a function in the
class to update some text or whatever, but over all it really cleans the
code up when you just don't do this sort of thing and, instead, send a
message. I've found that that messages typically get processed immediately
if the bandwidth is clear so the net effect on the user's experience is the
same, but the program runs much better and more reliably. Nothing like
popping up an AfxMessageBox() with no text in it because the DLL thread has
it's own resources :o)

I know you agree, I'm just adding comments to the thread (forum thread that
is, not the worker thread) :o)

Tom

"David Ching" <d...@remove-this.dcsoft.com> wrote in message
news:BZREj.1446$p24...@nlpi061.nbdc.sbc.com...

Aditya

unread,
Mar 21, 2008, 2:04:55 PM3/21/08
to
On Mar 21, 10:02 am, "Tom Serface" <tom.nos...@camaswood.com> wrote:
> I can't say for sure, but I'd guess the message queue is only getting full
> because you are stopping the main thread from processing messages. I don't
> know why that would hang it, but perhaps the OS puts it into a "Not
> Responding" mode when the message queue is full. In any case you can easily
> fix it using the advice given here in this thread.
>
> Tom
>
> "Aditya" <adityabo...@gmail.com> wrote in message

ya..tom that may be the one reason that OS periodically checking up
the message queues and if
some thread not processing the messages then it set to "Not responding
" state...for that ui becomes hangs
that why people always keep the main UI thread free..

thanks to all for ur valuable time and suggestions..
Aditya

David Wilkinson

unread,
Mar 21, 2008, 2:17:07 PM3/21/08
to
Aditya wrote:
> ya..tom that may be the one reason that OS periodically checking up
> the message queues and if
> some thread not processing the messages then it set to "Not responding
> " state...for that ui becomes hangs
> that why people always keep the main UI thread free..
>
> thanks to all for ur valuable time and suggestions..


Aditya:

I think you are still confused. The main thread does not check the message queue
of other threads. It checks its own message queue. And it cannot do that if it
is busy or sleeping.

Personally, I usually use worker threads, not UI threads. Then there are no
message queues outside the main thread. It's very simple:

1. The main thread just waits for messages and updates the GUI as appropriate,
but does not do any significant work.

2. The worker thread just works, and uses PostMessage() or SendMessage() to
transmit results back to the main thread.

Tom Serface

unread,
Mar 21, 2008, 4:02:35 PM3/21/08
to
No problem. Just to make you feel better, VS 2005 does this to me all the
time on Vista. It says "Not Responding" right on the title bar, then after
30 seconds or so it starts working again. I think it has something to do
with working with Visual SourceSafe through VPN and it takes way longer than
expected to update the check out status of files. I keep turning off VSS in
the IDE, but it keeps turning it back on again. I just live with it. I'm
not sure why other companies can do VSS like source code control through VPN
with reasonable speed, but Microsoft can not. I actually haven't tried this
with 2008 so maybe that's better, but I'm not holding out a lot of hope.
Anyway, I understandy your pain :o)

Tom

"Aditya" <adity...@gmail.com> wrote in message

news:1a11027e-c5e7-4328...@s19g2000prg.googlegroups.com...


> On Mar 21, 10:02 am, "Tom Serface" <tom.nos...@camaswood.com> wrote:
>> I can't say for sure, but I'd guess the message queue is only getting
>> full
>> because you are stopping the main thread from processing messages. I
>> don't
>> know why that would hang it, but perhaps the OS puts it into a "Not
>> Responding" mode when the message queue is full. In any case you can
>> easily
>> fix it using the advice given here in this thread.
>>
>> Tom
>>
>> "Aditya" <adityabo...@gmail.com> wrote in message

> ya..tom that may be the one reason that OS periodically checking up

Tom Serface

unread,
Mar 21, 2008, 4:04:27 PM3/21/08
to
Hi David,

I think what Aditya is saying is that the OS is checking the program and if
it has not processed messages for some time it puts Not Responding in the
title bar and hangs it up until it starts processing messages again. I
think he was causing the problem, but the symptom is the same as many other
times Vista (or XP but not as often) thinks a program is not doing what it
is supposed to be doing. For sure sleeping for 60 seconds would make it
look like it's not responding.

Tom

"David Wilkinson" <no-r...@effisols.com> wrote in message
news:uSe5E$3iIHA...@TK2MSFTNGP06.phx.gbl...

David Wilkinson

unread,
Mar 21, 2008, 4:25:25 PM3/21/08
to
Tom Serface wrote:
> Hi David,
>
> I think what Aditya is saying is that the OS is checking the program and
> if it has not processed messages for some time it puts Not Responding in
> the title bar and hangs it up until it starts processing messages
> again. I think he was causing the problem, but the symptom is the same
> as many other times Vista (or XP but not as often) thinks a program is
> not doing what it is supposed to be doing. For sure sleeping for 60
> seconds would make it look like it's not responding.

Tom:

Ah yes, the OP said the OS, not the main thread. Sometimes I think I must be
dyslexic, or at least I see what I expect to see, and not what is actually written.

Apologies to Aditya.

Aditya

unread,
Mar 22, 2008, 12:41:41 AM3/22/08
to
hi david...in the button click function i put sleep to just simulate
some big operation...instead of sleep i can put some time consuming
operation like searching a big file or in while loop for million
times....my main purpose was to know internally what happen if i don't
process messages for some time...is the messages remain in the message
queue or OS remove it and put the status to not responding...becuase
Microsoft don't allow to see the code for thread message queue or how
they are putting the messages in the message queue...
i think tom is right..if OS think the program is not processing the
messages then it set it to "Not Responding"

Aditya

Unknown

unread,
Mar 22, 2008, 11:36:34 AM3/22/08
to
On Fri, 21 Mar 2008 13:02:35 -0700, Tom Serface wrote:

>I'm not sure why other companies can do VSS like source code control through VPN
>with reasonable speed

Probably because their repositories are proper databases of some form,
not squillions of little files.

--
Bob Moore
http://bobmoore.mvps.org/
(this is a non-commercial site and does not accept advertising)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Do not reply via email unless specifically requested to do so.
Unsolicited email is NOT welcome and will go unanswered.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

David Ching

unread,
Mar 22, 2008, 11:55:06 AM3/22/08
to
<Bob Moore> wrote in message
news:8q9au3hju1dsgoa14...@4ax.com...

>>I'm not sure why other companies can do VSS like source code control
>>through VPN
>>with reasonable speed
>
> Probably because their repositories are proper databases of some form,
> not squillions of little files.
>

That and all the processing is done on the server, not the client that needs
to download every bit of raw data to diffs, etc. in the case of VSS.

-- David


Ajay Kalra

unread,
Mar 22, 2008, 10:27:45 PM3/22/08
to

"Aditya" <adity...@gmail.com> wrote in message
news:b6ad7510-66eb-4639...@s37g2000prg.googlegroups.com...

Messages do get queued but queue is not infinite and it will ultimately
spill over. I dont know the limit. Bottom line is that you should not to
anything which blocks the UI thread.

---
Ajay

Joseph M. Newcomer

unread,
Mar 23, 2008, 2:56:58 PM3/23/08
to
See below...

****
Youo answered your own question. It hangs because you explicitly told it to go to sleep,
and therefore do absolutely nothing, for 1 minute. If you want it to do anything, you
have to not do the sleep. A thread which is suspended in a sleep cannot do anything else.

It makes no sense to sleep in the main GUI thread. Don't do it.
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Joseph M. Newcomer

unread,
Mar 23, 2008, 3:01:39 PM3/23/08
to
The "not responding" is not a function of your app at all; it is done by the OS.
Periodically it sends a message to your app, and if the message does not get a response
within a small fixed period of time (a few seconds), the app is declared as "not
responding". This has nothing to do with your app at all.

As already pointed out, do not block your main GUI thread for any reason. Do not do
Sleep. Do not do a WaitForSingleObject or WaitForMultipleObjects to wait for threads. Do
not block your main thread.

See my essays on threading on my MVP Tips site.
joe

Joseph M. Newcomer

unread,
Mar 23, 2008, 3:08:01 PM3/23/08
to
It will have the same effect: it will block your main thread. If you want to simulate a
thread doing something for a long time, create a thread, and let that THREAD do the
Sleep() to simulate that it is doing something.

void CMyDialog::OnBnClickedRun()
{
AfxBeginThread(threadfunc, this);
}

/* static */ UINT CMyDialog::threadfunc(LPVOID p)
{
CMyDialog * me = (CMyDialog*)p;
Sleep(60000);
return 0;
}

But see my essays on message management and dialog control management. Note that what you
probably really want to do is

void CMyDialog::OnBnClickedRun()
{
running = TRUE;
AfxBeginThread(threadfunc, this);
updateControls();
}

void CMyDialog::updateControls()
{
c_Run.EnableWindow(!running);
}

/* static */ UINT CMyDialog(LPVOID p)
{
CMyDialog * me = (CMyDialog*)p;
... do stuff here
me->PostMessage(UWM_THREAD_IS_FINISHED);
return 0;
}

where UWM_THREAD_IS_FINISHED is a user-defined message of your own invention (see my essay
on message management)

Add to your message map

ON_MESSAGE(UWM_THREAD_IS_FINISHED, OnFinished)
or
ON_REGISTERED_MESSAGE(UWM_THREAD_IS_FINISHED, OnFinished)

where you have defined

LRESULT OnFinished(WPARAM, LPARAM);

and the function is

LRESULT CMyDialog::OnFinished(WPARAM, LPARAM)
{
running = FALSE; // thread is no longer running
updateControls();
return 0;
}

See my essays on threading, messaging, and dialog control management
joe

Joseph M. Newcomer

unread,
Mar 23, 2008, 3:10:11 PM3/23/08
to
The nominal limit of the PostMessage queue is 10,000 messages, but there is a Registry key
that can be set to change this limit.

Note that posting too many messages to the queue will delay WM_TIMER and WM_PAINT
messages, and can severely delay responsiveness to keyboard and mouse input.

I handle this by using an I/O Completion Port, posting the messages to the IOCP, and using
the OnIdle handler to dequeue and process a small number of messages at a time, to
minimize PostMessage queue saturation. This is described in my essay on I/O Completion
Ports.
joe

Joseph M. Newcomer

unread,
Mar 23, 2008, 3:11:46 PM3/23/08
to
See my earlier note on PostMessage queue saturation and you can see my essay on the use of
I/O Completion Ports to avoid this problem.
joe

On Fri, 21 Mar 2008 18:02:10 +0100, "Giovanni Dicanio" <giovanni...@invalid.com>
wrote:

Joseph M. Newcomer

unread,
Mar 23, 2008, 3:19:59 PM3/23/08
to
See below...

On Fri, 21 Mar 2008 10:33:14 -0700, "Tom Serface" <tom.n...@camaswood.com> wrote:

>I think this may be the biggest confusion. I know I still get caught by
>this at times. It is so easy to put in something like AfxMessageBox() into
>the worker thread and that just gets me (and I assume others) into trouble.
>It works sometimes, but... I've also been caught when I tried to do that
>sort of thing (UI) from a callback from a DLL function (like a message
>server listener) which may (even though I don't know it) be running on its
>own thread. My personal opinion these days is when in doubt send a message
>to the UI thread. I also never call functions direction in dialogs or views
>(except through UpdateAllViews()).

****
It is almost always a disaster to call UpdateAllViews from other than the main GUI thread.
I hope this is what you are actually doing (I've seen and had to fix any number of
disasters in code my clients send me because they don't understand that UpdateAllViews can
only be done in the main GUI thread)
****


>This is a tough thing to get used to
>since it's so easy to just grab a view pointer and call a function in the
>class to update some text or whatever, but over all it really cleans the
>code up when you just don't do this sort of thing and, instead, send a
>message. I've found that that messages typically get processed immediately
>if the bandwidth is clear so the net effect on the user's experience is the
>same, but the program runs much better and more reliably. Nothing like
>popping up an AfxMessageBox() with no text in it because the DLL thread has
>it's own resources :o)

*****
I believe it is always an error to pop up a MessageBox in a secondary thread; a secondary
thread has to be carefully designed as if a GUI does not exist.

PostMessage works up to a point, but see my earlier comments about PostMessage queue
saturation and the problems of delaying WM_TIMER and WM_PAINT messages; my trick is to use
an I/O Completion Port, post what I want to it, and use the OnIdle handler to dequeue the
messages. Neat trick is that you end up never blocking WM_TIMER, WM_PAINT, or ultimately
delaying mouse and keyboard messages to the point where the GUI is unusable.

I first hit this problem years ago when a client had an embedded system that worked just
fine for ordinary data, but when he turned on "internal debug trace" in his embedded
system, we saturated the message queue; clicking "stop" took over 30 seconds to simply
uncheck the box, and another two minutes to finally stop spewing the messages that had
been queued up. I invented the IOCP solution to solve that problem, and the result was
the GUI remains instantly responsive even if you have thousands of messages queued up
(because they aren't going into the PostMessage queue, but the secondary queue where they
are dequeued in small groups; see my essay)
joe

*****


>
>I know you agree, I'm just adding comments to the thread (forum thread that
>is, not the worker thread) :o)
>
>Tom
>
>"David Ching" <d...@remove-this.dcsoft.com> wrote in message
>news:BZREj.1446$p24...@nlpi061.nbdc.sbc.com...
>>
>> "Aditya" <adity...@gmail.com> wrote in message
>> news:e77e8622-9295-45c2...@i12g2000prf.googlegroups.com...
>>> ya u r correct ..we need to keep the primary thread free to process
>>> messages,
>>> messages from other threads or messages caused by user actions but my
>>> question is if i block
>>> it and during that period did some UI operation from other
>>> threads..why UI get hangs...is there any reason special reason like
>>> need
>>> to process the message immediately
>>
>> Perhaps you need to show the exact code you're talking about. It's not
>> clear what you mean by "UI operation from other threads." Only the
>> primary thread should do UI operations. Anything that takes a long time
>> should be on another thread. And the primary thread should not be looping
>> or sleeping while the other thread is working, or else it won't process
>> messages and hang.
>>
>> -- David
>>
>>

Giovanni Dicanio

unread,
Mar 23, 2008, 4:23:54 PM3/23/08
to

"Joseph M. Newcomer" <newc...@flounder.com> ha scritto nel messaggio
news:fqadu3poeb3hq6qrc...@4ax.com...

> See my earlier note on PostMessage queue saturation and you can see my
> essay on the use of
> I/O Completion Ports to avoid this problem.

Thanks Joe.

I was unaware of PostMessage queue saturation problem.

Giovanni


Joseph M. Newcomer

unread,
Mar 23, 2008, 9:34:53 PM3/23/08
to
It's a nasty one. Shocked me the first time I hit it...
joe

On Sun, 23 Mar 2008 21:23:54 +0100, "Giovanni Dicanio" <giovanni...@invalid.com>
wrote:

>

Dan Bloomquist

unread,
Mar 24, 2008, 2:31:44 AM3/24/08
to
Joseph M. Newcomer wrote:
> It's a nasty one. Shocked me the first time I hit it...
> joe
>
> On Sun, 23 Mar 2008 21:23:54 +0100, "Giovanni Dicanio" <giovanni...@invalid.com>
> wrote:
>
>> "Joseph M. Newcomer" <newc...@flounder.com> ha scritto nel messaggio
>> news:fqadu3poeb3hq6qrc...@4ax.com...
>>> See my earlier note on PostMessage queue saturation and you can see my
>>> essay on the use of
>>> I/O Completion Ports to avoid this problem.
>> Thanks Joe.
>>
>> I was unaware of PostMessage queue saturation problem.

I'm curious. I posted an example of this a few days ago. Are my posts
not coming through?

Post:
***
I put a thread in a sample dialog to see if I could break it.

Thread object:
struct TS
{
CString strT;
CDialog* pDlg;
bool bTReady;
};

class CA_Dialog_AppDlg : public CDialog
{
TS ts;
...
};

I'm sharing a CString that is on the dialog stack. It should have been
on the heap.

UINT Thread( LPVOID pParam )
{
TS& strct= *static_cast<TS*>( pParam );

for( long i= 0; ; ++i )
{
//if( strct.bTReady )
{
strct.strT.Format( _T("Test This %d"), i );
::PostMessage( *strct.pDlg, ID_CHECK_THREAD, 0, 0 );
strct.bTReady= false;
}
//Sleep( 5 );
//for( long j= 0; j < 20000; ++j )
;
}
return false;
}

In init dialog:
ts.pDlg= this;
ts.bTReady= true;
pThread= AfxBeginThread( Thread, &ts, THREAD_PRIORITY_LOWEST, 0,
CREATE_SUSPENDED );
pThread->m_bAutoDelete= FALSE;
pThread->ResumeThread( );

and member:
LRESULT CA_Dialog_AppDlg::OnCheckThread( WPARAM, LPARAM )
{
SetWindowText( ts.strT );
ts.bTReady= true;
return false;
}

With the 'if( strct.bTReady )' in the thread commented the dialog is
swamped with messages and is dead. But it would not crash and the title
bar updates! I figured that I would catch CString with an invalid
pointer and I may have if I'd kept going. But that is the point,
bTReady is used to make sure the thread is not changing data while the
app is using it. It also makes sure the thread doesn't post more
messages than the app can handle.

I also didn't stop the thread when the app quit, I just deleted it. But
to do it right it takes another semaphore that absolutely tells the
thread to exit. That means in every:

while( ! strct.bTReady && ! strct.bKill )
::Sleep( 5 );


In the exit:

ts.bKill= true;
WaitForSingleObject( pThread->m_hThread, INFINITE );
delete pThread;

Best, Dan.
***

And, Best, Dan.

Joseph M. Newcomer

unread,
Mar 24, 2008, 10:40:32 AM3/24/08
to
I have scrolled through the thread I have downloaded, and this is your only post...

Not to say that some other NG server might have them, but mine didn't.
joe

****
This is truly weird, because you are using a shared variable and bizarre simulated
locking, and there is no need to do ANY of this, because you can pass a pointer in the
message itself! This means that you aren't going to lose anything, and you don't need to
do ugly polling loops!

I wouldn't trust this code to work correctly in a multiprocessor.

Also, why not just write
strct.pDlg->PostMessage(ID_CHECK_THREAD);
which is much simpler?
****


> strct.bTReady= false;
> }
> //Sleep( 5 );
> //for( long j= 0; j < 20000; ++j )
> ;
> }
> return false;
>}
>
>In init dialog:
> ts.pDlg= this;
> ts.bTReady= true;
> pThread= AfxBeginThread( Thread, &ts, THREAD_PRIORITY_LOWEST, 0,
>CREATE_SUSPENDED );
> pThread->m_bAutoDelete= FALSE;
> pThread->ResumeThread( );
>
>and member:
>LRESULT CA_Dialog_AppDlg::OnCheckThread( WPARAM, LPARAM )
>{
> SetWindowText( ts.strT );
> ts.bTReady= true;
> return false;
>}
>
>With the 'if( strct.bTReady )' in the thread commented the dialog is
>swamped with messages and is dead. But it would not crash and the title
>bar updates! I figured that I would catch CString with an invalid
>pointer and I may have if I'd kept going. But that is the point,
>bTReady is used to make sure the thread is not changing data while the
>app is using it. It also makes sure the thread doesn't post more
>messages than the app can handle.

****
None of this makes sense, because in a multithreaded environment, you should not be
sharing a variable without using an interlock. I don't see any mutex or CRITICAL_SECTION
here, and that will be fatal. This is really marginal code, especially in a
multiprocessor. Without the strc.bTReady test, there is no way that this can be safe. You
are creating a fragile and probably incorrect solution to the problem. If you really want
to "throttle" the sending thread, you should be using a semaphore with a max count of 1,
and just put a butter pointer in the message, rather than using these bizarre interlocks.

sending thread:
WaitForSingleObject(strct.semaphore, INFINITE);
strct.pDlg->PostMessage(ID_DATA, buffer);
handler:
CString * s = (CString *)wParam;
...use string
delete s;
ReleaseSemaphore(semaphore, 1, NULL);

That's what semaphores are for. The code you show cannot be trusted to be correct in all
situations, and by using polling, you are wasting significant amounts of energy.
****


>
>I also didn't stop the thread when the app quit, I just deleted it. But
>to do it right it takes another semaphore that absolutely tells the
>thread to exit. That means in every:

****
I don't see a semaphore, I see a boolean variable. But yes, you should be using the
boolean variable. See also my essay on worker threads, because if you are blocked on the
WFSO you can use WFMO with a shutdown event to break loose.

Polling hacks are just hacks.
****


>
>while( ! strct.bTReady && ! strct.bKill )
> ::Sleep( 5 );

****
Anything between Sleep(1) and Sleep(15) is the same as Sleep(15). Note that sleep times
are always rounded up to the next clock tick interval. This is actually exceptionally
poor multithreaded style. You should not be polling. Polling is just a hack, and not
usually a safe one, either.
joe
****


>
>
>In the exit:
>
>ts.bKill= true;
>WaitForSingleObject( pThread->m_hThread, INFINITE );
>delete pThread;
>
>Best, Dan.
>***
>
>And, Best, Dan.

Tom Serface

unread,
Mar 24, 2008, 11:15:13 AM3/24/08
to
Joe,

I think the problem was that OP (and some of us) didn't understand where the
"Not Responding" message was coming from. To be fair, I see this a lot in
Vista (way more than XP) especially when using Visual Studio. There are
some times when it will be nearly 15-30 seconds before the UI comes back
into play. I'm not sure what triggers it. Thanks for your explanation of
the message queue limit. That supports the conclusions we came to that
blocking the GUI thread will cause the OS to eventually twit the program
into Not Responding mode.

Tom

"Joseph M. Newcomer" <newc...@flounder.com> wrote in message
news:agefu391ij7oc61dj...@4ax.com...

Joseph M. Newcomer

unread,
Mar 24, 2008, 12:16:03 PM3/24/08
to
If the OS finds the window is "not responding", it replaces the window with a "shadow"
window, so the window you are seeing is not actually the window. The "shadow" window
allows you to drag around the window and do some other operations.
joe

Dan Bloomquist

unread,
Mar 24, 2008, 1:04:10 PM3/24/08
to
Joseph M. Newcomer wrote:
>
> On Mon, 24 Mar 2008 06:31:44 GMT, Dan Bloomquist <publ...@lakeweb.com> wrote:
>
>> UINT Thread( LPVOID pParam )
>> {
>> TS& strct= *static_cast<TS*>( pParam );
>>
>> for( long i= 0; ; ++i )
>> {
>> //if( strct.bTReady )
>> {
>> strct.strT.Format( _T("Test This %d"), i );
>> ::PostMessage( *strct.pDlg, ID_CHECK_THREAD, 0, 0 );
> ****
> This is truly weird, because you are using a shared variable and bizarre simulated
> locking, and there is no need to do ANY of this, because you can pass a pointer in the
> message itself! This means that you aren't going to lose anything, and you don't need to
> do ugly polling loops!

Hi Joe,
I think you have misunderstood my objective.

UINT Thread( LPVOID pParam )
{

...


for( long i= 0; ; ++i )

//This is the worker loop, it is doing real work.
{
...
//Now it has progress data for the GUI thread
//if that thread is ready for another message
//it will post it.


if( strct.bTReady )
{
strct.strT.Format( _T("Test This %d"), i );
::PostMessage( *strct.pDlg, ID_CHECK_THREAD, 0, 0 );

strct.bTReady= false;
}
}
}

> I wouldn't trust this code to work correctly in a multiprocessor.

Does this still apply?

>
> sending thread:
> WaitForSingleObject(strct.semaphore, INFINITE);

> That's what semaphores are for. The code you show cannot be trusted to be correct in all
> situations, and by using polling, you are wasting significant amounts of energy.

My objective was an example of 'not' blocking the thread and keeping the
GUI updated. In that light, do you see a problem with the way I use the
semaphore strct.bTReady?

Best, Dan.

Joseph M. Newcomer

unread,
Mar 24, 2008, 1:29:05 PM3/24/08
to
See below...

****
It isn't a semaphore; it is a bool variable. In rereading it, I see that the Sleep() is
not part of the test loop, but now you have a situation in which it will not update unless
the other thread has processed the data, which means that you will lose information by not
sending it at all. If your system is redundant enough that you can afford to lose
information, then it works, but if you need reliable communication by which everything you
want to send is received, it doesn't work. I usually have live data from some embedded
system, and if I were to discard it because the other thread had not responded by reading
the one-and-only "pending" message, I'd be losing significant amounts of information. You
did not point out that this is an information-losing algorithm. As such, it is deceptive
because, while it might work for a progress bar, it doesn't work for pretty much anything
else. The thread should not assume that the receiver doesn't want to see, for example,
progress messages, which it might also be logging to a file or doing something else with.
So the overall architecture is very fragile (a change in the receiver to do something
significant will now find itself in an information-losing situation)
joe
****

Dan Bloomquist

unread,
Mar 24, 2008, 2:47:59 PM3/24/08
to

The wiki author calls it a 'binary semaphore', better known as a mutex.
http://en.wikipedia.org/wiki/Semaphore_(programming)

I would think any object that is used as a signal between threads would
qualify as a semaphore.

> In rereading it, I see that the Sleep() is
> not part of the test loop, but now you have a situation in which it will not update unless
> the other thread has processed the data, which means that you will lose information by not
> sending it at all. If your system is redundant enough that you can afford to lose
> information, then it works, but if you need reliable communication by which everything you
> want to send is received, it doesn't work.

Sorry for the confusion. I thought what I was doing was clear in the
original post. It was an experiment to purposefully break it. One, by
swamping the GUI thread and second, by letting the GUI thread at the
data while it was changing.

And yes, of course it would have to be more elaborate to ensure data is
not lost.

Best, Dan.

Doug Harrison [MVP]

unread,
Mar 24, 2008, 4:30:13 PM3/24/08
to
On Mon, 24 Mar 2008 18:47:59 GMT, Dan Bloomquist <publ...@lakeweb.com>
wrote:

>>> My objective was an example of 'not' blocking the thread and keeping the

>>> GUI updated. In that light, do you see a problem with the way I use the
>>> semaphore strct.bTReady?
>> ****
>> It isn't a semaphore; it is a bool variable.
>
>The wiki author calls it a 'binary semaphore', better known as a mutex.
>http://en.wikipedia.org/wiki/Semaphore_(programming)
>
>I would think any object that is used as a signal between threads would
>qualify as a semaphore.

It is a bool variable, and as such, it's just dumb data. It's neither a
mutex nor a semaphore, data types which provide signal and wait operations
useful for multithreaded programming. For example, consider the mutex
operations:

1. Wait: This operation acquires the mutex if it is signaled, such that no
other thread can acquire it at the same time. If the mutex isn't available,
the thread enters an efficient wait state and blocks until the mutex
becomes signaled.

2. Signal: This operation releases the mutex so that it may be acquired
again by the Wait operation.

Clearly, bool is nothing like this. You're using strct.bTReady sort of like
an event, which you poll during your loop. Joe's comment about it being
unsafe on a multiprocessor has to do with memory visibility; even though
Thread A sets a bool to true, and Thread B observes it, the two threads
don't necessarily share a completely consistent view of memory. For
multiprocessor systems that require memory barriers (e.g. Itanium), you
will have to use a type or operations that provide the necessary barriers.
All the Windows synchronization objects provide them as necessary.

--
Doug Harrison
Visual C++ MVP

Joseph M. Newcomer

unread,
Mar 24, 2008, 5:13:48 PM3/24/08
to
See below...

****
I see no similar example in that article. Note that what you have done is not what is in
the article, or even close to what the article describes. In order to follow what the
article does, you need an atomic operation (InterlockedCompareExchange) and you have to
spin-wait; you do not wait, you just skip sending the message. That is not a semaphore,
not even close to a semaphore; it is just a boolean flag.

[There is actually an algorithm for doing a spin lock on a machine without an atomic
compare-and-exchange instruction, and working it out was something I had to do in 1968 to
pass an exam. It was NOT as simple as storing a TRUE or FALSE in a BOOL.]

You have no mutex here; you have something that just skips sending a message if a boolean
flag is set. There is no mutual exclusion in the sense that anyone means "mutex". You
have no reliable mutual exclusion at all! Let's look at the code:

for( long i= 0; ; ++i )
{

if( strct.bTReady ) //
// mov r, strct.bTReady [1]
// tst r
// je skip

{
strct.strT.Format( _T("Test This %d"), i );
::PostMessage( *strct.pDlg, ID_CHECK_THREAD, 0, 0 );
strct.bTReady= false;

// mov r, 1
// mov strct.bTReady, r [2]
}

// skip:

... some computation
}

If two threads are running this code, and both get to instruction [1], BOTH of them pick
up strct.bTReady. Or, on a uniprocessor, thread A executes [1], gets preempted, and the
other thread runs and executes [1]. Both see it is TRUE. Both proceed to spend a lengthy
amount of time formatting data, stepping on top of each other in potentially disastrous
ways, and then both set it to FALSE at step [2]. This cannot possibly work! While it is
less likely to fail on a uniprocessor, it will still fail eventually. A hyperthreaded
processor will increase the chances, a multicore processor will increase the chances even
more, and with multiple threads using it on multiple cores, it rapidly becomes a
certainty.

Now, if you had done

if(!InterlockedCompareExchange(strc.bTReady, FALSE, TRUE)) /* do nothing */ ;

then you would have a spin-lock which would actually work, and you could safely use it.
Lousy from a CPU utilization viewpoint, but at least correct. But what you have is not
even a mutex, because it does not guarantee exclusion, and it is not multiprocessor safe.

If you had done
if(InterlockedCompareExchange(strct.bTReady, FALSE, TRUE))
{
... code as above
}

you would still have an information-losing transformation but it would at least not have
the failure potential of the current code, which is completely unsynchronized.

You can't take a random piece of code and call it a "mutex", because a "mutex" has very
specific meaning. After Dijkstra's work, other researchers introduced the concept of what
we now call a "mutex", which is a mutual exclusion primitive with recursive acquisition
semantics. A mutex is quite different from the "binary semaphore", because a semaphore
has no recursive acquisition semantics. A CRITICAL_SECTION is named after what Dijkstra
had called the *code* guarded by the semaphore, but as used in Windows it means "a very
efficient mutex" because it has both recursive acquisition semantics and avoids calling
the kernel for scheduling until a counted spin-lock expires. The notion of timed waits was
also introduced after Dijkstra; he never quite approved of them because he thought a
properly-designed system would not require a timeout of any sort; and strictly speaking,
the CRITICAL_SECTION uses the "timeout" as an internal way of obtaining efficiency while
still maintaining the philosophical correctness of the original mutex (or, if you ignore
recursive acquisition, semaphore) concept.

One of the other interesting challenges we had (which was part of my PhD qualifier exam)
was the multiple-reader-single-writer problem, which the kernel implements as the
Executive Resource (ERESOURCE) type. You can do it with a lot of convoluted programming
with mutexes (mutice? mutices?) but it isn't straightforward. We have no user-level
equivalent of this.

You do not have a semaphore,you do not have a mutex, you have an unprotected and
unsynchronized BOOL variable. Nothing more (and, the code is basically incorrect).
****


>
>I would think any object that is used as a signal between threads would
>qualify as a semaphore.

****
No. Dijkstra very carefully specified how a semaphore behaves, and if it doesn't behave
like that, it is NOT a semaphore. Those of us who worry about synchronization would never
recognize the code you wrote as being anywhere vaguely close to the concept of semaphore.
The word has a very specific semantic meaning. Otherwise, you could use an Event as a
"semaphore", which a number of beginners try to do, and it always fails, because and Event
is NOT a Semaphore. The word "semaphore" does NOT mean "any arbitrary signaling
mechanism", it very specifically means "a counted exclusion object that blocks the thread
when the count is 0; a wait operation decrements the count, and a release operation
increments the count". Dijkstra called the wait operation "P" and the release operation
"V"; we call them WaitForSingleObject(..., INFINITE) and ReleaseSemaphore(...,1, NULL) if
we want to model Dijkstra's original semaphores.

I took one of my Operating Systems classes from Nico Habermann, who was one of the best
students, or perhaps THE best student, that Dijkstra had. (Nico was a friend, and died
far too young of a coronary, apparently after returning from jogging. I worked with him
on several projects, and he was head of the Computer Science Department at CMU for many
years while I was there and long after I left. He also created the PhD qualifier exam I
struggled with, but years later told me I had done the best job he'd ever seen).

You can't take some random concept (such as setting a BOOL) and call it a "semaphore".
****


>
>> In rereading it, I see that the Sleep() is
>> not part of the test loop, but now you have a situation in which it will not update unless
>> the other thread has processed the data, which means that you will lose information by not
>> sending it at all. If your system is redundant enough that you can afford to lose
>> information, then it works, but if you need reliable communication by which everything you
>> want to send is received, it doesn't work.
>
>Sorry for the confusion. I thought what I was doing was clear in the
>original post. It was an experiment to purposefully break it. One, by
>swamping the GUI thread and second, by letting the GUI thread at the
>data while it was changing.

****
You didn't actually create a reliable situation during which the concurrent access could
be achieved. To really break it, you would need to use two threads trying to write the
string, and you could significantly increase the chances of this by running it in any
multicore processor.
****


>
>And yes, of course it would have to be more elaborate to ensure data is
>not lost.

****
And rather important in a lot of cases!

Dan Bloomquist

unread,
Mar 24, 2008, 7:19:31 PM3/24/08
to
Joseph M. Newcomer wrote:
> See below...
> On Mon, 24 Mar 2008 18:47:59 GMT, Dan Bloomquist <publ...@lakeweb.com> wrote:
>
>> Joseph M. Newcomer wrote:
>>>> UINT Thread( LPVOID pParam )
>>>> {
>>>> ...
>>>> for( long i= 0; ; ++i )
>>>> //This is the worker loop, it is doing real work.
>>>> {
>>>> ...
>>>> //Now it has progress data for the GUI thread
>>>> //if that thread is ready for another message
>>>> //it will post it.
>>>> if( strct.bTReady )
>>>> {
>>>> strct.strT.Format( _T("Test This %d"), i );
>>>> ::PostMessage( *strct.pDlg, ID_CHECK_THREAD, 0, 0 );
>>>> strct.bTReady= false;
>>>> }
>>>> }
>>>> }
>>>>
>>>> GUI updated. In that light, do you see a problem with the way I use the
>>>> semaphore strct.bTReady?
>>> ****
>>> It isn't a semaphore; it is a bool variable.
>> The wiki author calls it a 'binary semaphore', better known as a mutex.
>> http://en.wikipedia.org/wiki/Semaphore_(programming)
> ****
> I see no similar example in that article. Note that what you have done is not what is in
> the article, or even close to what the article describes. In order to follow what the
> article does, you need an atomic operation (InterlockedCompareExchange) and you have to
> spin-wait; you do not wait, you just skip sending the message. That is not a semaphore,
> not even close to a semaphore; it is just a boolean flag.

Ok, officially I concede it should not be called a semaphore as I have
not wrapped it in a class with waits. The wiki page needs fixing:

"The simplest kind of semaphore is the "binary semaphore", used to
control access to a single resource, which is essentially the same as a
mutex. A binary semaphore is always initialized with the value 1. When
the resource is in use, the accessing thread calls P(S) to decrease this
value to 0, and restores it to 1 with the V operation when the resource
is ready to be freed."

> If two threads are running this code, and both get to instruction [1], BOTH of them pick
> up strct.bTReady. Or, on a uniprocessor, thread A executes [1], gets preempted, and the
> other thread runs and executes [1]. Both see it is TRUE.

Not the way I wrote it. See below...

> Both proceed to spend a lengthy
> amount of time formatting data, stepping on top of each other in potentially disastrous
> ways, and then both set it to FALSE at step [2].

Ok, now you have two worker threads working on the same data in the same
way? Sure, that won't work. I never dreamed it would.

> This cannot possibly work! While it is
> less likely to fail on a uniprocessor, it will still fail eventually.

Not what I wrote. The worker thread affects the shared data. The GUI
thread has no access as it never got a message to process. The worker is
done, sets the flag and sends a message. (I did get that out of order in
the example. It would have lead to a failure eventually. But that's a
bug.) Now the worker thread will not touch the data or the flag again
until the GUI member uses the data and resets the flag.

> A hyperthreaded
> processor will increase the chances, a multicore processor will increase the chances even
> more, and with multiple threads using it on multiple cores, it rapidly becomes a
> certainty.

It won't fail because the worker thread excludes its own access. It
won't touch the data until the GUI member says it is done with it. The
only thing that could go wrong is if the message got lost.

I'll leave the following as it is an interesting account of the
evolution of threads. I read all your stuff.

I don't see the flaw. But I'll never call a flag a semaphore again. (pun
intended :)

> ****
>> I would think any object that is used as a signal between threads would
>> qualify as a semaphore.
> ****
> No. Dijkstra very carefully specified how a semaphore behaves, and if it doesn't behave
> like that, it is NOT a semaphore. Those of us who worry about synchronization would never
> recognize the code you wrote as being anywhere vaguely close to the concept of semaphore.
> The word has a very specific semantic meaning. Otherwise, you could use an Event as a
> "semaphore", which a number of beginners try to do, and it always fails, because and Event
> is NOT a Semaphore. The word "semaphore" does NOT mean "any arbitrary signaling
> mechanism", it very specifically means "a counted exclusion object that blocks the thread
> when the count is 0; a wait operation decrements the count, and a release operation
> increments the count". Dijkstra called the wait operation "P" and the release operation
> "V"; we call them WaitForSingleObject(..., INFINITE) and ReleaseSemaphore(...,1, NULL) if
> we want to model Dijkstra's original semaphores.
>
> I took one of my Operating Systems classes from Nico Habermann, who was one of the best
> students, or perhaps THE best student, that Dijkstra had. (Nico was a friend, and died
> far too young of a coronary, apparently after returning from jogging. I worked with him
> on several projects, and he was head of the Computer Science Department at CMU for many
> years while I was there and long after I left. He also created the PhD qualifier exam I
> struggled with, but years later told me I had done the best job he'd ever seen).
>
> You can't take some random concept (such as setting a BOOL) and call it a "semaphore".

http://pages.cs.wisc.edu/~remzi/Classes/537/Fall2005/Lectures/lecture6.ppt
See "Producer/Consumer: Single Buffer". It is the same concept but
without waits. But it is not random.

> ****
>>> In rereading it, I see that the Sleep() is
>>> not part of the test loop, but now you have a situation in which it will not update unless
>>> the other thread has processed the data, which means that you will lose information by not
>>> sending it at all. If your system is redundant enough that you can afford to lose
>>> information, then it works, but if you need reliable communication by which everything you
>>> want to send is received, it doesn't work.
>> Sorry for the confusion. I thought what I was doing was clear in the
>> original post. It was an experiment to purposefully break it. One, by
>> swamping the GUI thread and second, by letting the GUI thread at the
>> data while it was changing.
> ****
> You didn't actually create a reliable situation during which the concurrent access could
> be achieved. To really break it, you would need to use two threads trying to write the
> string, and you could significantly increase the chances of this by running it in any
> multicore processor.

In the example I commented:
//if( strct.bTReady )
And noted that in the text. I'd imagine if I waited long enough the GUI
read would have caught CString with invalid data. But as important, it
would swamp the GUI thread and the app would not respond. Even worse,
the OS sees the app possessing messages so doesn't see it as 'not
responding'. Should be tested on vista.

> ****
>> And yes, of course it would have to be more elaborate to ensure data is
>> not lost.
> ****
> And rather important in a lot of cases!
> ****

To wit. I have one dictionary that lives in a message thread. You can
have multiple views running worker threads that do spell checking. The
user can right click, spell check or thesaurus words while the view is
spell checking and and marking misspelled words.

I do know how important it is to make sure everyone behaves.

Best, Dan.

Joseph M. Newcomer

unread,
Mar 24, 2008, 11:23:09 PM3/24/08
to
See below...

****
The wiki article is correct. Your code is not an embodiment of that description, because
the P operation will wait and the V operation will signal to dequeue or activate a waiting
thread. Since you do neither, you have not done what the wiki article describes.
****


>
>> If two threads are running this code, and both get to instruction [1], BOTH of them pick
>> up strct.bTReady. Or, on a uniprocessor, thread A executes [1], gets preempted, and the
>> other thread runs and executes [1]. Both see it is TRUE.
>
>Not the way I wrote it. See below...
>
>> Both proceed to spend a lengthy
>> amount of time formatting data, stepping on top of each other in potentially disastrous
>> ways, and then both set it to FALSE at step [2].
>
>Ok, now you have two worker threads working on the same data in the same
>way? Sure, that won't work. I never dreamed it would.

****
But with proper synchronization and without the use of a single variable, it can work,
which is why the solution is not going to work as written.
*****


>
>> This cannot possibly work! While it is
>> less likely to fail on a uniprocessor, it will still fail eventually.
>
>Not what I wrote. The worker thread affects the shared data. The GUI
>thread has no access as it never got a message to process. The worker is
>done, sets the flag and sends a message. (I did get that out of order in
>the example. It would have lead to a failure eventually. But that's a
>bug.) Now the worker thread will not touch the data or the flag again
>until the GUI member uses the data and resets the flag.

****
Yes, but now you have an information-losing transaction. You can hope to process at most
one message per timeslice on a uniprocessor, but you can expect to generate tens to
hundreds of thousands of messages per timeslice. This is HUGE data loss!
****

The code shown in the slide "Semaphore implementation" is simply WRONG and cannot be made
to work correctly unless it is rewritten. InterlockedIncrement and InterlockedDecrement
MUST be used on an x86, and on other architectures it can be even worse; as Doug points
out, memory barriers are required on some architectures. But the code shown could not be
made to work correctly on any architecture that has existed in history. For a semaphore
count-and-test to work correctly, you must have an atomic operation to increment and test,
and the notion of writing
S->value--;
if(S->value > 0) ...
is impossible to implement correctly. The slide as such is complete nonsense. I am not
aware of a single computer architecture in the last 50 years that would allow this code to
compile into a proper implementation of a semaphore. On the other hand, every
multiprocessor and/or interrupt-aware architecture had an atomic test-and-set (read:
InterlockedCompareExchange) instruction, certainly the Bendix G20 dual-processor system
designed around 1963, and it did not invent the concept, which was already known. The
IBM/360 had a test-and-set when it was released in 1964 or thereabouts. I just checked,
and the IBM 7030 ("Stretch") computer in 1956 had a SWAP instruction that, given the
architecture of the time, would have been an atomic operation from which a semaphore could
have been created.

The "mutual exclusion with semaphores" slide only works for a binary semaphore that is
initialized to 1.

Note that a binary semaphore used as a semaphore makes it impossible to implement a
multiprocessor-safe circular-list-walk algorithm; for that to work correctly you need
recursive acquisition semantics of a Windows-style Mutex; a Semaphore of max value 1 will
not work correctly; the thread will deadlock itself.

The "thread join" example works only when waiting for a single child thread and will not
work as WaitForMultipleObjects will work, so that example is misleading in that it
suggests that it is a general solution.

A binary semaphore with a single buffer works, but it is terribly limiting in that you are
blocking both the producer and consumer, thus reducing concurrency; the threads run in
lockstep and therefore are no more efficient than a simple subroutine call.

The circular buffer example is the first example that even approaches reality. The
problem is that it is insufficient for multiple producer threads or multiple consumer
threads and as such is misleading as a solution.

The correct solution (such as the one I show in my essay on semaphores) where the
semaphore controls allocation and an additional mutex is required for synchronization to
the queue and pool. Correct implementation requires two mutexes and two semaphores (as I
do in my class on System Programming).

The answers to the last slide are:

Producer #1/Consumer #1 are nonsense. They won't work and can't be made to work.
Producer #2/Consumer #2 are correct but inefficient
Producer #3/Consumer #3 are correct and slightly more efficient

The maximally efficient solution (this is the solution I require in my course) is not
shown!

Producer: Consumer:
sem_wait(&poolsemaphore); sem_wait(&queuesemaphore);
sem_wait(&poolmutex); sem_wait(&queuemutex);
ptr = AllocateFromPool(); ptr = Dequeue();
sem_signal(&poolmutex); sem_signal(&queuemutex);
fill(ptr); use(ptr);
sem_wait(&queuemutex); sem_wait(&poolmutex);
enqueue(ptr); FreeToPool(ptr);
sem_signal(&queuemutex); sem_signal(&poolmutex);
sem_signal(&queuesemaphore); sem_signal(&poolsemaphore);

Even with a circular buffer, it does not make sense to have a single mutex, because the
head pointer and the free pointer are separate values and do not require a single mutex to
lock them.

poolsemaphore is initialized to the number of elements in the pool
queuesemaphore is initialized to 0

The trick question in my course is that the poolsemaphore cannot be initialized to the
number of elements in the pool until the number of elements are actually in the pool (most
students miss this, and I then have them run a test case that fails because of this).

So the set of slides you cite are not a particularly good example, starting with the fact
that the purported implementation of a semaphore is flat-out WRONG.
*****


>
>> ****
>>>> In rereading it, I see that the Sleep() is
>>>> not part of the test loop, but now you have a situation in which it will not update unless
>>>> the other thread has processed the data, which means that you will lose information by not
>>>> sending it at all. If your system is redundant enough that you can afford to lose
>>>> information, then it works, but if you need reliable communication by which everything you
>>>> want to send is received, it doesn't work.
>>> Sorry for the confusion. I thought what I was doing was clear in the
>>> original post. It was an experiment to purposefully break it. One, by
>>> swamping the GUI thread and second, by letting the GUI thread at the
>>> data while it was changing.
>> ****
>> You didn't actually create a reliable situation during which the concurrent access could
>> be achieved. To really break it, you would need to use two threads trying to write the
>> string, and you could significantly increase the chances of this by running it in any
>> multicore processor.
>
>In the example I commented:
> //if( strct.bTReady )
>And noted that in the text. I'd imagine if I waited long enough the GUI
>read would have caught CString with invalid data. But as important, it
>would swamp the GUI thread and the app would not respond. Even worse,
>the OS sees the app possessing messages so doesn't see it as 'not
>responding'. Should be tested on vista.
****

But I have a workaround which avoids this and does not saturate the queue, and does not
lose messages or drop data.
*****


>
>> ****
>>> And yes, of course it would have to be more elaborate to ensure data is
>>> not lost.
>> ****
>> And rather important in a lot of cases!
>> ****
>
>To wit. I have one dictionary that lives in a message thread. You can
>have multiple views running worker threads that do spell checking. The
>user can right click, spell check or thesaurus words while the view is
>spell checking and and marking misspelled words.

*****
This does not require synchronization unless you can add to the dictionary. Also, this is
an example of the multiple-reader-single-writer paradigm, which can be implemented by some
complex mutex/semaphore actions which I would not attempt to re-create off the top of my
head, which is a problem not previously discussed here. Or, alternatively, you have
implemented the "central manager" pattern , which is also not something previously
discussed in this discussion thread.
*****


>
>I do know how important it is to make sure everyone behaves.
>
>Best, Dan.

Aditya

unread,
Mar 25, 2008, 8:48:02 AM3/25/08
to
On Mar 24, 8:15 pm, "Tom Serface" <tom.nos...@camaswood.com> wrote:
> Joe,
>
> I think the problem was that OP (and some of us) didn't understand where the
> "Not Responding" message was coming from. To be fair, I see this a lot in
> Vista (way more than XP) especially when using Visual Studio. There are
> some times when it will be nearly 15-30 seconds before the UI comes back
> into play. I'm not sure what triggers it. Thanks for your explanation of
> the message queue limit. That supports the conclusions we came to that
> blocking the GUI thread will cause the OS to eventually twit the program
> into Not Responding mode.
>
> Tom
>
> "Joseph M. Newcomer" <newco...@flounder.com> wrote in messagenews:agefu391ij7oc61dj...@4ax.com...

>
> >I have scrolled through the thread I have downloaded, and this is your only
> >post...
>
> > Not to say that some other NG server might have them, but mine didn't.
> > joe
>
> > On Mon, 24 Mar 2008 06:31:44 GMT, Dan Bloomquist <publi...@lakeweb.com>

> > wrote:
>
> >>Joseph M. Newcomer wrote:
> >>> It's a nasty one. Shocked me the first time I hit it...
> >>> joe
>
> >>> On Sun, 23 Mar 2008 21:23:54 +0100, "Giovanni Dicanio"
> >>> <giovanni.dica...@invalid.com>
> >>> wrote:
>
> >>>> "Joseph M. Newcomer" <newco...@flounder.com> ha scritto nel messaggio
> > email: newco...@flounder.com

Hi Joe,
thanks for ur comments..its really helpful to know the
internal...thats why i started with simple sleep() of main thread...

Thanks
Aditya

0 new messages