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
| Вернуться в корень Архива |