I have a strange 开发者_运维知识库problem, a deadlock problem, where if I pause the program using Visual Studio and inspect the threads I can only see two threads waiting on the lock. No thread appears to be inside the lock scope! Is Visual Studio just lying or how can a lock statement exit without releasing the lock?
Thanks
This can happen under the following circumstances. Suppose you have
Enter();
try
{
Foo();
}
finally
{
Exit();
}
and a thread abort exception is thrown after the Enter but before the try. Now the monitor has been entered but the finally will never run because the exception was thrown before the try.
We've fixed this flaw in C# 4. In C# 4 the lock statement is now generated as
bool mustExit = false;
try
{
Enter(ref mustExit);
Foo();
}
finally
{
if (mustExit) Exit();
}
Things can still go horribly wrong of course; aborting a thread is no guarantee that the thread ever aborts, that finally blocks ever run, and so on. You could end up in the unhandled exception event handler with the lock still taken. But this is at least a little better.
This can happen if you manually call Monitor.Enter(something)
without calling Monitor.Exit
.
Do you have any explicit calls to Monitor.Enter
/ Monitor.TryEnter
in your code? Can you see the stack traces for those waiting threads? If so, look at where they're waiting - that should make it obvious.
Are you by any chance calling yield return from within a lock statement from a thread pool thread?
If that is the case, you may want to look at Yielding surprises
This blog post describes a bug (I got locked out) I encountered when I combined those three things the wrong way. Luckly I was albe to resolve the issue with a small change to the code.
精彩评论