?
Solved

Multi Threaded Application

Posted on 2000-04-14
17
Medium Priority
?
413 Views
Last Modified: 2013-12-03
I am converting my single threaded application into a Multi threaded app. Everything seems to work ok until I added Mutex's to prevent code accessing the same shared data structures.

What happened was that when a thread created a window, while the other thread was calling WaitSingleObject the whole app would freeze. I found this gem in MSDN

Wait Functions and Creating Windows
You have to be careful when using the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. If you have a thread that uses a wait function with no time-out interval, the system will deadlock. Two examples of code that indirectly creates windows are DDE and COM CoInitialize. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than WaitForSingleObject

I looked at MsgWaitForMultipleObjects but I'm not sure what to do. If MsgWaitForMultipleObjects returns a value indicating a Message Waiting, then what should it do. If I dispatch all the messages waiting, then the program tends to have problems, because of a timing issue (ie the message wasnt intended to be dispatched because some data structures have yet to be initialised by another part of the program.

Does anyone have some sound advice on using these functions?
0
Comment
Question by:philsmicronet
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 4
  • 3
  • +2
17 Comments
 
LVL 1

Author Comment

by:philsmicronet
ID: 2715174
Also,
I tried MsgWaitForMutlitpleObjects and it only seemed to return when input was available on the input queue. My call is

    dwRet = MsgWaitForMultipleObjects(1, &hMutex, FALSE, INFINITE, QS_ALLINPUT);

What I want is it to return if hMutex can be signalled, or if the deadlock situation has occurred and some messages need to be dispatched



0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2715261
It is impossible to give you the answer without knowledge what exactly you are doing.
Could you place your code here?

Also it's much more simple and faster to use critical sections for the same app, instead of mutexes.
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2715277
If you want to protect some data, do the following:

WinMain()
{
InitializeCriticalSection(&cs);

.....

DeleteCriticalSection(&cs)
}


EnterCriticalSection(&cs);
// Access to data here - reading or writting
LeaveCriticalSection(&cs);
0
Get your Disaster Recovery as a Service basics

Disaster Recovery as a Service is one go-to solution that revolutionizes DR planning. Implementing DRaaS could be an efficient process, easily accessible to non-DR experts. Learn about monitoring, testing, executing failovers and failbacks to ensure a "healthy" DR environment.

 
LVL 32

Expert Comment

by:jhance
ID: 2716079
Well the most common problem causing hangs in a multithreaded app with mutexes is a deadlock.  I suspect you have a case where both threads are waiting on the mutex and neither can proceed since both are waiting on the other.

Take a look at your code and make sure you don't have any mutual dependencies.

Beyond this, it could be just about anything based on what little you've said.
0
 
LVL 1

Author Comment

by:philsmicronet
ID: 2718112
I dont think that this is the actual problem. In MSDN is states that you will have problems if one thread is creating a Window and you are using Mutexes. This is exactly the problem. I tried swapping them to CriticalSections but had the same problem
0
 
LVL 15

Expert Comment

by:NickRepin
ID: 2718396
The problem is that you incorrectly use them. Without your code, it's impossible to help you.
0
 
LVL 32

Expert Comment

by:jhance
ID: 2718782
>I dont think that this is the actual problem

Well then, I guess that settles it.  You don't know what the problems _IS_ but you know what it _ISN'T_!

I'm sure glad things are working now.
0
 
LVL 1

Author Comment

by:philsmicronet
ID: 2719615
Things still are not working. My code is very complex. I am going to put a mutex log into it so I can see if at anystage I am Getting a mutex and not releasing it.
0
 
LVL 4

Expert Comment

by:wylliker
ID: 2719806
As others have said, very difficult to diagnose or to propose solutions without some good or at least a good description of the sequence of events.

Whatever you do make sure that you are never passing INFINITE for the wait value for any of the wait functions.

If you are waiting in the UI thread in some message handler, such as WM_CREATE or WM_INITDIALOG, or any regular message for that matter, you shouldn't.
Instead, at the end of your handler Post a message to yourself and in that message's handler do your Wait call with a timeout of, like, 500 milliseconds. After the Wait returns -if you get WAIT_TIMEOUT then simply repost the message to yourself.  When you get a signaled return post a message whose handler actually gets the information your thread needs.

0
 
LVL 1

Author Comment

by:philsmicronet
ID: 2721323
The two things I am waiting on are

1. Access to files. I do a wait, position the file and then read or write and then release the wait

2. Shared structures. Some of these are in response to WM_CREATE, WM_INITDIALOG etc.

Number two is obviously the problem child. The code is fairly simple in that its

WaitforSingleObject();
Access Linked List
ReleaseMutex();

Is this still going to be a problem.

I actually found my original problem that started this question. I actually locked a mutex twice and released it once. I was under the misunderstanding that this would cause the original thread to lock, yet it does not.

0
 
LVL 4

Expert Comment

by:wylliker
ID: 2721402
The only trouble you will have is if you have an INFINITE wait timeout in your wait function - unless I am misinterpreting the MSDN docs.
0
 
LVL 1

Author Comment

by:philsmicronet
ID: 2725155
This is exactly what I want to do. Your idea of posting emssages sounds difficult, as the programs are simple accessing shared data structures.
0
 

Expert Comment

by:dentener
ID: 2725894
Try using Critical Sections in stead of mutexes. Mutexes can be used across process boundaries and are more expensive in terms of processor time.

Critical sections are more easier to use, but do not prevent a deadlock in your program.

A deadlock is often caused by weakly constructed code, where multiple threads are waiting for the same thing.

Try revising your code, in such a manner, so that the deadlock can be avoided...

Regards,

Paul
0
 
LVL 4

Expert Comment

by:wylliker
ID: 2727682
I know you are only trying to simply access shared data structures, BUT, the MSDN docs state that you can have deadlock conditions and that your windows MUST process messages - you can't do that if you are in an INFINITE wait - especially in messages at window and/or dialog creation.

You can use CriticalSection objects for shared access as long as the data you need to obtain is already available but you only want to prevent multiple  access to the data structures.  Otherwise, if you have to wait - potentially forever - you will be in the same place as with Wait...(INFINITE)

As for posting messages it would only be something like so ...

At the end of WM_INITDIALOG just add a post of your own message

PostMessage(hwnd, WM_MYMSG_WAITFORDATA, 0, 0)

Add a handler in your message loop ..

case WM_MYMSG_WAITFORDATA
     WaitResult = Wait...(hMutex, 500);
     if(WaitResult == WAIT_TIMEOUT)
         PostMessage(hwnd, WM_MYMSG_WAITFORDATA,0,0)
     else
     if(WaitResult == WAIT_OBJECT_0)
          PostMessage(hwnd, WM_MYMSG_GETDATA, 0, 0)
     else
     if(WaitResult == WAIT_ABANDONED)
       ... Yikes - the thread holding the mutex went bye-bye!!! What happens now ???
     break;

case WM_MYMSG_GETDATA
     ... Do whatever you need to do here
     ... Get data ... populate controls etc
     break;



0
 
LVL 1

Author Comment

by:philsmicronet
ID: 2730547
Are you saying that I can use CriticalSections without a problem or will I have the same issue as with Mutex's. Also I only have a mutex locked for a very small amount of time. Is this still going to cause an issue
0
 
LVL 4

Accepted Solution

by:
wylliker earned 400 total points
ID: 2735310
You can use a CriticalSection object as long as you are only serializing access to your linked list to one thread accessing it at a time.  You shouldn't use CriticalSections to wait for data in the linked list to be populated - such as a query from a database or retrieval from a remote system - or any place where a failure can occur that could cause the critical section to be blocked forever. Then you will have an infinite wait which would be no different from calling a Wait function with the INFINITE timeout value.

What I am saying (encouraging) is that you should not have an INFINITE wait.  I can think of no reason for having an INFINITE wait anywhere - I don't even think it should be an option provided by the API as it encourages a shortcut that can contribute to de-stabilization of the OS.

It is like using TerminateThread or TerminateProcess - they should never be used (even Microsoft uses them in their code regularly).  Read what they do - and think of the problems that can occur from their use.  Just another shortcut providing the easy out - when careful consideration of Multiprocess/Multithread design decisions should be examined.

For your particular situation ...

What happens if the thread holding the Mutex dies unexpectedly and you get WAIT_ABANDONED?

Can you really guarantee the wait will be short?

If so, then set the time limit to be say 3 seconds or 10 seconds but not make it INFINITE - but you must be able to guarantee this maximum time and guarantee that the thread providing the shared data can't/won't die in the interim.

You will probably be OK if you are using this as an internal application - but if this code is going to customers, you can never guarantee the environment under which your code will run?

If the data the thread is going to be using can take awhile to come back, you can (by the posting method) allow for a Cancel or Quit by the user.  You can also properly respond to SHUTDOWN messages and behave properly (as far as windows is concerned) under most conditions.

I am not trying to complicate what you are doing - I am just giving you food for thought - so you don't find yourself with an application where you can only say  - "Works almost all of the time" or support engineers saying "I know you reported a problem but we can't reproduce it" or support folks saying "if your system stops responding - reboot your machine".



0
 
LVL 1

Author Comment

by:philsmicronet
ID: 2736885
Ok thanks for the advise. The access is only to things like linked lists where I am adding, deleting or searching for stuff. The time would be very small as these lists normally contain 10->30 entries. My code no longer uses a INFINITE but waits for 1 second and then checks to see if any messages are waiting in its message loop. Upon one of the other conditions, (eg WAIT_ABANONED, the call fails and the program abondons its attempts to look at the list, and fails the call and the thread terminates in a nice way.
Thanks for you help
0

Featured Post

Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question