473,385 Members | 1,311 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Threading problem (incredibly straightforward mutex usage not working)

I've been having strange thread conflicts, and after moving the relevant
mutex higher and higher I've finally determined that the mutex doesn't
seem to be working at all.

Here is the relevant code:

private static Mutex previewMutex = new Mutex();

private static void preview (string source, string target)
{
try
{
previewMutex.WaitOne();
if (previewerThread != null && previewerThread.IsAlive)
{
evl.WriteEntry("WaitingForPreviewerThread");
previewerThread.Join();
evl.WriteEntry("FinishedWaiting");
}
DocSearch.previewSource = source;
DocSearch.previewTarget = target;
previewerThread = new Thread (DocSearch.previewStarter);
previewerThread.Priority = ThreadPriority.Normal;
previewerThread.Name = "PreviewDownloader";

previewerThread.Start();
previewMutex.ReleaseMutex();
}
catch(Exception err)
{
evl.WriteEntry(err.ToString());
}
}
What's happening is the mutex is not blocking properly. I look in the
event log and see the WaitingForPreviewerThread message three times in a
row, with no messages at all in between. I've verified that log message
isn't anywhere else in the code and this is the only place previewMutex
is used. The really messed up thing is that this function is only
called from a GUI event handler (OnChange event for a ListView). From
my understanding from doing MFC and Win32 programming, the GUI should
only have one active thread by default anyway, meaning this shouldn't be
possible regardless of the mutex. The code works as expected if the
user slowly arrows through the listbox including all the expected event
log messages.

Here's what the thread does, if it matters:

public static void backgroundPreview()
{
try
{
Common.GetFile(DocSearch.previewSource,DocSearch.p reviewTarget);

Common.SendMessage (Common.mainHwnd, Common.WM_PREVIEWREADY, 0, 0);
}
catch (Exception err)
{
evl.WriteEntry(err.ToString());
}
}

GetFile calls a web service and downloads a file. SendMessage is the
win32 API.
The handler for WM_PREVIEW is in the same form class that activates the
thread, and it displays a picture in an activeX control.

Any help is greatly appreciated!

Tyler
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #1
11 3052
Tyler Sample <st**@qwest.net> wrote:
I've been having strange thread conflicts, and after moving the relevant
mutex higher and higher I've finally determined that the mutex doesn't
seem to be working at all.


Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #2
The Mutex.WaitOne will not block if no other thread has acquired the mutex. You don't show any other thread attempting to acquire the mutex. What behavior were you expecting from the Mutex?

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

I've been having strange thread conflicts, and after moving the relevant
mutex higher and higher I've finally determined that the mutex doesn't
seem to be working at all.

<snip>
Nov 16 '05 #3
Somehow preview() is being entered two to three times without exiting
before the Join() blocks and locks up the whole application.

I'll try to do a sample application that demonstrates the problem..
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #4
Okay, I was unable to reproduce the problem in a simple application (big
surprise, right?)

The test application did seem to confirm my suspicion that the normal
behavior of the application is one thread per GUI. Debugging the
problem application SEEMS to confirm this (can't figure out how to
programmatically determine a thread's unique ID, though, so I'm not
sure)

What I'm ending up with is TWO messages, back to back in the event log
saying:
WaitingForPreviewerThread
GUI

Can everyone plainly see how this shouldn't be possible? The code is
failing to execute the "FinishedWaiting" log entry and is somehow
disappearing into thin air (apparently releasing the mutex on its way
out). There's only one line of code between those two log entries!
WriteEntry throws exceptions when it fails.

Is it possible a control I'm using is hosing the code stack?
I really can't even imagine where to begin solving this problem, and I
must.

The other possibility is that I somehow am ending up with two GUI
threads provided by the system for a very short period of time, but that
seems less likely than hosed memory.

//This is part of the handler for an OnChange event:
private static void preview (string source, string target)
{
try
{
previewMutex.WaitOne();
if (previewerThread != null && previewerThread.IsAlive)
{

evl.WriteEntry("WaitingForPreviewerThread\r\n"+Thr ead.CurrentThread.Name
);
previewerThread.Join();
evl.WriteEntry("FinishedWaiting");
}
DocSearch.previewSource = source;
DocSearch.previewTarget = target;
previewerThread = new Thread (DocSearch.previewStarter);
previewerThread.Priority = ThreadPriority.Normal;
previewerThread.Name = "PreviewDownloader";
previewerThread.Start();
previewMutex.ReleaseMutex();
}
catch(Exception err)
{
evl.WriteEntry(err.ToString());
}

}

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #5
Two things:

You must not use GUI elements from any thread other than the one that created them. I'm not sure whether thats what you mean by "normal behavior being one thread per GUI".

You can get hold of the thread id using AppDomain.GetCurrentThreadId();

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

Okay, I was unable to reproduce the problem in a simple application (big
surprise, right?)

The test application did seem to confirm my suspicion that the normal
behavior of the application is one thread per GUI. Debugging the
problem application SEEMS to confirm this (can't figure out how to
programmatically determine a thread's unique ID, though, so I'm not
sure)

What I'm ending up with is TWO messages, back to back in the event log
saying:
WaitingForPreviewerThread
GUI

Can everyone plainly see how this shouldn't be possible? The code is
failing to execute the "FinishedWaiting" log entry and is somehow
disappearing into thin air (apparently releasing the mutex on its way
out). There's only one line of code between those two log entries!
WriteEntry throws exceptions when it fails.

Is it possible a control I'm using is hosing the code stack?
I really can't even imagine where to begin solving this problem, and I
must.

The other possibility is that I somehow am ending up with two GUI
threads provided by the system for a very short period of time, but that
seems less likely than hosed memory.
Nov 16 '05 #6
Well, I meant that unless I specifically do GUI stuff in one of my
threads, I have only one thread that should handle user messages
(events, mouse moves, etc..)

Thanks for the tip on the thread id. It is the same thread. It's the
same thread somehow never completing the function, so I guess this isn't
a threading problem.

Damn...Now I just have no idea where to even start. I guess I eliminate
the unsafe ActiveX controls one by one and see if that helps...

Uggh.

Well, thanks for the help!

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #7
Do you you DoEvents in your code? This can cause re-entrancy

Also, if you call an MTA based COM component from an STA thread you can get re-entrancy

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

Well, I meant that unless I specifically do GUI stuff in one of my
threads, I have only one thread that should handle user messages
(events, mouse moves, etc..)

Thanks for the tip on the thread id. It is the same thread. It's the
same thread somehow never completing the function, so I guess this isn't
a threading problem.

Damn...Now I just have no idea where to even start. I guess I eliminate
the unsafe ActiveX controls one by one and see if that helps...

Uggh.

Well, thanks for the help!
Nov 16 '05 #8
No DoEvents. Not really sure about the MTA com components. That's
pretty possible. Although they certainly aren't called between the two
logging functions (one of which isn't firing). Also, wouldn't the mutex
keep that kind of expected/normal re-entrancy from happening? Somehow
that mutex is getting released, or there is a bug in the mutex class
itself, which I find unlikely.

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #9
The mutex won't prevent this as its thread sensitive. As its the same thread re-entering it will just aquire a second lock on the mutex

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

No DoEvents. Not really sure about the MTA com components. That's
pretty possible. Although they certainly aren't called between the two
logging functions (one of which isn't firing). Also, wouldn't the mutex
keep that kind of expected/normal re-entrancy from happening? Somehow
that mutex is getting released, or there is a bug in the mutex class
itself, which I find unlikely.

Nov 16 '05 #10
Oh yeah...That's true! So, I guess that leaves me some hope that
everything is working okay, although...

I'm a little vague on how I could have a legitimate re-entrancy problem
in the same thread between these lines of code:

evl.WriteEntry("WaitingForPreviewerThread\r\n"+App Domain.GetCurrentThrea
dId().ToString());
previewerThread.Join();
evl.WriteEntry("FinishedWaiting");

It doesn't really seem that there's any way for the thread to escape
there, not matter what I may be doing elsewhere..I could certainly see
how a *different* thread could enter again...but the same one? None of
these calls are wrapped. They are straight system calls..No opportunity
to re-enter the message loop as far as I can tell! I'm catching
exceptions and logging them, and there aren't any, so....

If I'm incorrect there, I would love to read a technical article
explaining my mistake.

Also, does Join() work like a WaitForSingleObject(threadHandle) call did
in C++? Or is there some deviousness possible in that call?

Thanks for all the help so far. I'm definitely much closer to solving
this problem than before...

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #11
Okay, I found the problem. This was referred to earlier, but I assumed
it mentioned as deliberate behavior on the part of the controls I was
calling. I didn't realize that Microsoft built in message pumping to
their blocking calls. I'm particularly thrilled that they didn't
document it at all! Wow. I'm ALMOST speechless :) Great. Now I have
to synchronize my main application thread with itself. I see why they
did it, but I have no idea why it's not clearly documented in the
relevant function calls.

http://blogs.msdn.com/cbrumme/archiv.../02/66219.aspx

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 16 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Alina | last post by:
Hello I'm working with a disconnected DataSet and I wish to make thread-safe the "add new rows" method. I try like this, but does not work: public class MyXmlDataDoc { ........
3
by: ron | last post by:
If I use the System.Threading.ThreadPool.QueueUserWorkItem to spawn a new threaded process, will this process be executed regardless of whether or not the current process ends prior to completion...
5
by: ste | last post by:
this code not work: it is no possible Exit from Monitor Why ? thank ste //////// using System; using System.Collections;
4
by: Bardo | last post by:
Hi, I have a situation where I am capturing both a WMI event utilising the "ManagementEventWatcher" in the "System.Management" namespace, and a corresponding event ("EntryWritten") raised from...
16
by: One Handed Man \( OHM - Terry Burns \) | last post by:
Sorry if this gets duplicated, but I posted it and cant see it for a long time so repost. . . I have an application which is writing to a graphics object, the main UI thread and a worker thread...
17
by: One Handed Man \( OHM - Terry Burns \) | last post by:
Assumes a Form with a Panel on it., Does the Mutex have to be within the address of a thread start address ? Cheers - OHM '----------- *************** ---------------- Private...
6
by: MobileBoy36 | last post by:
Hi All, I want to make a LogFile class that is thread safe. I use a Mutex for it. But the behavior of the class is not that normal. In a c# guide I read you can achieve it by simply using...
2
by: Jeroen | last post by:
Hi all, I've been trying to get my head around threading. Here's an example from the book I'm reading: /***************************/ Mutex m = null; const string name = "xyz"; try
126
by: Dann Corbit | last post by:
Rather than create a new way of doing things: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html why not just pick up ACE into the existing standard:...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.