Solved

Multi Threaded Application

Posted on 2000-04-14
17
380 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
  • 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
 
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
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

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

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This article describes how to programmatically preset the "Pages per Sheet" option that's available with most printer drivers.   This setting lets you do "n-Up" printing, where two, four, or more pages are printed on each sheet of paper. If your …
This article surveys and compares options for encoding and decoding base64 data.  It includes source code in C++ as well as examples of how to use standard Windows API functions for these tasks. We'll look at the algorithms — how encoding and decodi…
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…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.

762 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

Need Help in Real-Time?

Connect with top rated Experts

28 Experts available now in Live!

Get 1:1 Help Now