Can Monitor.Enter
throw any exception. I am doing a code review and find that Monitor.Enter
is before try block. Do you see any issues with in?
Monitor.Enter(...)
try
{
...
}
finally
{
Monitor.Exit(..)
}
Can Monitor.Enter
throw any exception. I am doing a code review and find that Monitor.Enter
is before try block. Do you see any issues with in?
Monitor.Enter(...)
try
{
...
}
finally
{
Monitor.Exit(..)
}
This is the correct pattern, whether Enter()
throws (can throw) or not.
Only after the call to Enter()
succeeds your code is under the responsibility to call Exit()
.
Suppose the call to Enter()
fails. Then calling the corresponding Exit()
is simply incorrect, it will make matters worse. So Enter()
has to be outside (before) the try block.
Hans Passant's comment is of course correct. If Monitor.Enter
throws before the lock is taken then you do not want the finally to run. If it throws after the lock is taken and after the try is entered, then the lock is released. (More on this later.) But if the throw happens after the lock is taken but before the try is entered, then the lock will never be cleaned up.
This is a rare but possible situation.
In C# 4 we changed the codegen of the lock statement so that the monitor enter is inside the try. This ensures that the lock is always released if something throws after the lock is taken. However, note that this might still be wrong. If something throws after the lock is taken then whatever non-atomic mutation the lock is protecting might be half-completed, and the finally block then unlocks the lock and allows access to the inconsistent state! The fundamental problem here is that you shouldn't be throwing inside a lock in the first place.
See my article about the issue for more discussion.
Monitor.Enter
can throw at least the following exceptions
null
Enter
has it's Interrupt
method invoked.If it acquires the lock, then no.
But an exception might be thrown between the Monitor.Enter
and the try
block.
The recommended method is the new Enter method, new in .NET 4:
public static void Enter( obj, ref bool lockTaken )