Multi Threaded Application

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?
Who is Participating?
wyllikerConnect With a Mentor Commented:
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".

philsmicronetAuthor Commented:
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

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.
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

If you want to protect some data, do the following:




// Access to data here - reading or writting
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.
philsmicronetAuthor Commented:
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
The problem is that you incorrectly use them. Without your code, it's impossible to help you.
>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.
philsmicronetAuthor Commented:
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.
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.

philsmicronetAuthor Commented:
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

Access Linked List

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.

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.
philsmicronetAuthor Commented:
This is exactly what I want to do. Your idea of posting emssages sounds difficult, as the programs are simple accessing shared data structures.
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...


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 ..

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

     ... Do whatever you need to do here
     ... Get data ... populate controls etc

philsmicronetAuthor Commented:
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
philsmicronetAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.