Thread Deadlocking, recomendations needed?
prmslick -- prmslick@infi.net
Thursday, February 22, 1996
VC++4, MFC:
Thanks to all of the helpful responses I now know (or strongly suspect) why I
could not successfully halt a worker thread. I got several good sugestions
about how to halt the thread. I beleive any of them will work. One of you
folks mentioned a possible deadlock. A painful review of my code showed just
that. But I'm a little green here and don't know exactly what is the best way
to get around the deadlock.
Heres an overview of the app.
SDI application.
Two threads, a primary and a worker.
Primary thread controls an I/O status window, and a dialog box. Both of which
recieve i/o messages from the worker thread.
Worker thread, loops until a TimeToExit flag is set. (Could also be an event as
I've been advised). The flag is checked at the top and bottom of the loop. In
the middle of the loop, I/O activity is directed to the dialog box and status
window (of the primary thread) via Cwnd->SendMessage(...) calls.
Strategy to End thread from Primary Thread.
Set TimeToExit flag to TRUE;
WaitForSingleObject(WorkerThreadHandle)
Deadlock:
In the middle of the worker thread, I/O was recieved from the com port. The
worker thread advised the status window and dialog box of the activity with Cwnd->SendMessage(...)
calls. The Primary Thread is blocked waiting for the worker thread to end and
won't process the messages. The SendMessage() call waits until the message was
processed before continuing. Thus a deadlock.
I've tried (at a previous time) to use PostMessage() but the performance
dropped significantly.
I imagine programmers with multithread experience have encountered this and
similar problems in the past. Although I have several books that cover threads
in general, none of the really discuss deadlock scenerios and how to avoid
them. Richter/Locke's book Windows95 a developers guide dosn't really address
much MFC, and my review of the text indicates he's working more in a "hook"
like environment. I'm afraid if there is an answer in his book, its went over
my head.
Any and all comments would be greatly appreaciated. The last volley of
responses have taught me a lot. Hopefully I'll be able to contribute here in
time.
prmslick@infi.net
Using Pegasus Mail Win95 and OS2 Warp
David W. Gillett -- DGILLETT@expertedge.com
Friday, February 23, 1996
[Mini-digest: 2 responses]
> Strategy to End thread from Primary Thread.
> Set TimeToExit flag to TRUE;
> WaitForSingleObject(WorkerThreadHandle)
>
> Deadlock:
> In the middle of the worker thread, I/O was recieved from the com port. The
> worker thread advised the status window and dialog box of the activity with Cwnd->SendMessage(...)
> calls. The Primary Thread is blocked waiting for the worker thread to end and
> won't process the messages. The SendMessage() call waits until the message was
> processed before continuing. Thus a deadlock.
If the worker thread can be sending messages to the UI thread after
TimeToExit is set, then (obviously?) the UI thread should stll be in
its message loop. This suggests that the UI thread should not begin
its WaitForSingleObject until it gets a message (posted, not sent)
that the worker thread has seen and acknowledges the flag.
[Checking at both the top and the bottom of the loop is redundant --
the fact that it's a loop puts these two checks right next to each
other.]
> I've tried (at a previous time) to use PostMessage() but the
> performance dropped significantly.
Actually, overall performance with PostMessage() should be better
than with SendMessage(), because time-consuming thread-switches are
reduced. Timeliness, however, can suffer, and this can negatively
impact the user's *perception* of the program's performance.
One idea you might try is to bump the priority of the UI thread by
a notch while mostly using PostMessage.
> I imagine programmers with multithread experience have encountered
> this and similar problems in the past. Although I have several
> books that cover threads in general, none of the really discuss
> deadlock scenerios and how to avoid them. Richter/Locke's book
> Windows95 a developers guide dosn't really address much MFC, and
> my review of the text indicates he's working more in a "hook" like
> environment. I'm afraid if there is an answer in his book, its
> went over my head.
I suspect that the coverage of threads and synchronization in that
book may be a little skimpy, because Richter covers them in great
detail in "Advanced Windows".
Dave
-----From: "Mark F. Fling"
Thanks for you're more complete description of the primary and work
threads. You're problem arises when you block the primary thread and
shut down the message pump of the application. I'm assuming by your
description you've got a dialog box up along with some form of status
indication, such as a progress bar or page counter, or the like.
I'm assuming you create your worker I/O thread in response to some
menu command or during OnInitInstance. If so, simply issue the
CreateThead/afxBeginThread call and continue on. There's no need to
block anything in the main (user interface) thread. Thus, the
message loop of the application still runs and accepts/processes
window update messages.
The I/O worker thread should then be able to post update messages to
the main window using SendNotifyMessge, which returns immediately if
the posting thread did not create the window. You might also need to
call UpdateWindow from the background thread to ensure a repaint
of the main window.
Your user interface contains a modal dialog box? Why? The whole idea
of worker threads is to improve the responsiveness of the user
interface thread and eliminate a "mode". Otherwise, you'd move your
I/O loop into your app and use traditional OnIdle processing to keep
the app semi-responsive. I gather your status thingy is on the main
window informing the user of the background I/O status. If the user
wants to stop the I/O, give em a menu item. I suggest you ditch the
dialog box.
This isn't a deadlock issue - it's really a design issue. Deadlocks
are simply manifestations of too-complex multithreaded designs, IMHO.
Pierre De Boeck -- pde@miscrit.be
Monday, February 26, 1996
prmslick wrote:
> Heres an overview of the app.
>
> SDI application.
> Two threads, a primary and a worker.
Why not create a third thread dedicated to the status window and
activity. You will have
- a primary thread that handles initialisation,
termination, creation of the two sub threads and
waiting for the dead of these two threads
(WaitForMultipleObject)
- the worker thread that sends messages to the staus
thread. Among these messages is a special one to
signal that the status thread must die.
- the status thread that processes the messages and
terminates whenn it receives the special "exit"
message.
So the termination process will look like this:
- the primary thread set the TimeToExit flag to TRUE
and waits for the dead of the two threads.
- the worker thread detects that the flag is TRUE, sends
the "exit" message to the status thread with the
Cwnd->SendMessage(...) call, and exit.
- the status thread receives the "exit" message and
exit.
- the primary thread is signaled and terminates.
[Moderator's question: Could you explain the advantage to this
approach over the 2-thread approach? It seems heavy-handed to
me, given that the primary thread just sits there when it
could be displaying status during its idle time.]
--
Pierre De Boeck
Mission Critical, Wijnegemhofstraat 199, B-3071 Erps-Kwerps
(Belgium)
Phone: +32 2 759 95 60 Fax: +32 2 759 27 60
email: pde@miscrit.be
///
(. .)
---------------------------------oOO--(_)--OOo------------------
----
Pierre De Boeck -- pde@miscrit.be
Wednesday, February 28, 1996
Pierre De Boeck wrote:
>
> prmslick wrote:
> > Heres an overview of the app.
> >
> > SDI application.
> > Two threads, a primary and a worker.
>
> Why not create a third thread dedicated to the status window and
> activity. You will have
> - a primary thread that handles initialisation,
> termination, creation of the two sub threads and
> waiting for the dead of these two threads
> (WaitForMultipleObject)
> - the worker thread that sends messages to the staus
> thread. Among these messages is a special one to
> signal that the status thread must die.
> - the status thread that processes the messages and
> terminates whenn it receives the special "exit"
> message.
>
> So the termination process will look like this:
> - the primary thread set the TimeToExit flag to TRUE
> and waits for the dead of the two threads.
> - the worker thread detects that the flag is TRUE, sends
> the "exit" message to the status thread with the
> Cwnd->SendMessage(...) call, and exit.
> - the status thread receives the "exit" message and
> exit.
> - the primary thread is signaled and terminates.
>
> [Moderator's question: Could you explain the advantage to this
> approach over the 2-thread approach? It seems heavy-handed to
> me, given that the primary thread just sits there when it
> could be displaying status during its idle time.]
>
You are totally right! The primary thread can acts as the
"status" thread but its WaitForSingleObject(hWorkerThread,..)
call must be done AFTER the receiption of the special "exit"
message stemming from the worker thread. This ensures a
safe-deadlock situation since
- the series of messages m0,m1,...exit are guaranteed to
be catched by the status thread (since it is not yet
in its waiting event call)
- the WaitForSingleObject() is guaranteed to terminate
since at this point, the worker thread have sent its
"exit" message and thus it is dead or is dying.
--
Pierre De Boeck
Mission Critical, Wijnegemhofstraat 199, B-3071 Erps-Kwerps
(Belgium)
Phone: +32 2 759 95 60 Fax: +32 2 759 27 60
email: pde@miscrit.be
///
(. .)
---------------------------------oOO--(_)--OOo------------------
----
John Addis -- jaddis@erols.com
Thursday, February 29, 1996
prmslick wrote:
> Strategy to End thread from Primary Thread.
> Set TimeToExit flag to TRUE;
> WaitForSingleObject(WorkerThreadHandle)
>
> Deadlock:
> In the middle of the worker thread, I/O was recieved from the com port. The
> worker thread advised the status window and dialog box of the activity with Cwnd->SendMessage(...)
> calls. The Primary Thread is blocked waiting for the worker thread to end and
> won't process the messages. The SendMessage() call waits until the message was
> processed before continuing. Thus a deadlock.
>
>
> prmslick@infi.net
> Using Pegasus Mail Win95 and OS2 Warp
How about checking the TimeToExit flag immediately before calling
SendMessage()?
--
John Addis Master of Time and Space
jaddis@erols.com C++, MFC, Win32, Win95, TCP/IP
"Invalid or missing REALITY.COM Universe halted."
Marty Fried -- mfried@linex.com
Sunday, March 03, 1996
At 11:39 PM 2/29/96 -0500, John Addis wrote:
>prmslick wrote:
>> Strategy to End thread from Primary Thread.
>> Set TimeToExit flag to TRUE;
>> WaitForSingleObject(WorkerThreadHandle)
>> . . .
>How about checking the TimeToExit flag immediately before calling
>SendMessage()?
Wouldn't that just reduce the chances, rather than eliminate the
problem? What if the worker thread gets prempted between checking
the flag and sending the message?
One possibility that comes to mind is this: after setting the TimeToExit
flag in the Primary thread, perhaps do a WaitForSingleObject with a fairly
short timeout, and if the return value is WAIT_TIMEOUT, process pending
messages, then loop back to WaitForSingleObject again, until you don't
timeout.
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Marty Fried (mfried@linex.com)
Marin County, California
| Вернуться в корень Архива
|