I have the following code:
using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
if (mut.WaitOne(new TimeSpan(0, 0, 30)))
{
// Some code that deals with a specific TCP port
// Don't want this to run at the same time in another process
}
}
I've set a breakpoint within the if block, and ran the same code within another instance of Visual Studio. As expected, the .WaitOne call blocks. However, to my surprise, as soon as I continue in the first instance and the using block terminates, I get an exception in the second process about an abandoned Mutex.
The fix is to call ReleaseMutex:
using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
if (mut.WaitOne(new TimeSpan(0, 0, 30)))
{
// Some code that deals with a specific TCP port
// Don't want this to run twice in multiple processes
}
mut.ReleaseMutex();
}
Now, things work as expected.
My Question: Usually the point of an IDisposable is it cleans up whatever state you put things in. I could see perhaps having multiple waits and releases within a using block, but when the handle to the Mutex is disposed, shouldn't it get released automatically? In other words, why do I need to call ReleaseMutex if I'm in a using block?
I'm also now concerned that if the code within the if block crashes, I'll have abandoned mutexes lying around.
Is there any benefit to putting Mutex in a using block? Or, should I just new up a Mutex instance, wrap it in a try/catch, and call ReleaseMutex() within the finally block (Basically implementing exactly what I thought Dispose() would do)
The documentation explains (in the "Remarks" section) that there is a conceptual difference between instantiating a Mutex object (which does not, in fact, do anything special as far as synchronization goes) and acquiring a Mutex (using WaitOne). Note that:
WaitOne returns a boolean, meaning that acquiring a Mutex can fail (timeout) and both cases must be handled
When WaitOne returns true, then the calling thread has acquired the Mutex and must call ReleaseMutex, or else the Mutex will become abandoned
When it returns false, then the calling thread must not call ReleaseMutex
So, there's more to Mutexes than instantiation. As for whether you should use using anyway, let's take a look at what Dispose does (as inherited from WaitHandle):
protected virtual void Dispose(bool explicitDisposing)
{
if (this.safeWaitHandle != null)
{
this.safeWaitHandle.Close();
}
}
As we can see, the Mutex is not released, but there is some cleanup involved, so sticking with using would be a good approach.
As to how you should proceed, you can of course use a try/finally block to make sure that, if the Mutex is acquired, that it gets properly released. This is likely the most straightforward approach.
If you really don't care about the case where the Mutex fails to be acquired (which you haven't indicated, since you pass a TimeSpan to WaitOne), you could wrap Mutex in your own class that implements IDisposable, acquire the Mutex in the constructor (using WaitOne() with no arguments), and release it inside Dispose. Although, I probably wouldn't recommend this, as this would cause your threads to wait indefinitely if something goes wrong, and regardless there are good reasons for explicitly handling both cases when attempting an acquire, as mentioned by #HansPassant.
This design decision was made a long, long time ago. Over 21 years ago, well before .NET was ever envisioned or the semantics of IDisposable were ever considered. The .NET Mutex class is a wrapper class for the underlying operating system support for mutexes. The constructor pinvokes CreateMutex, the WaitOne() method pinvokes WaitForSingleObject().
Note the WAIT_ABANDONED return value of WaitForSingleObject(), that's the one that generates the exception.
The Windows designers put the rock-hard rule in place that a thread that owns the mutex must call ReleaseMutex() before it exits. And if it doesn't that this is a very strong indication that the thread terminated in an unexpected way, typically through an exception. Which implies that synchronization is lost, a very serious threading bug. Compare to Thread.Abort(), a very dangerous way to terminate a thread in .NET for the same reason.
The .NET designers did not in any way alter this behavior. Not in the least because there isn't any way to test the state of the mutex other than by performing a wait. You must call ReleaseMutex(). And do note that your second snippet is not correct either; you cannot call it on a mutex that you didn't acquire. It must be moved inside of the if() statement body.
Ok, posting an answer to my own question. From what I can tell, this is the ideal way to implement a Mutex that:
Always gets Disposed
Gets Released iff WaitOne was successful.
Will not get abandoned if any code throws an exception.
Hopefully this helps someone out!
using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
if (mut.WaitOne(new TimeSpan(0, 0, 30)))
{
try
{
// Some code that deals with a specific TCP port
// Don't want this to run twice in multiple processes
}
catch(Exception)
{
// Handle exceptions and clean up state
}
finally
{
mut.ReleaseMutex();
}
}
}
Update: Some may argue that if the code within the try block puts your resource in an unstable state, you should not release the Mutex and instead let it get abandoned. In other words, just call mut.ReleaseMutex(); when the code finishes successfully, and not put it within the finally block. The code acquiring the Mutex could then catch this exception and do the right thing.
In my situation, I'm not really changing any state. I'm temporarily using a TCP port and can't have another instance of the program run at the same time. For this reason, I think my solution above is fine but yours may be different.
One of the primary uses of a mutex is to ensure that the only code which will ever see a shared object in a state which doesn't satisfy its invariants is the code which (hopefully temporarily) put the object into that state. A normal pattern for code which needs to modify an object is:
Acquire mutex
Make changes to object which cause its state to become invalid
Make changes to object which cause its state to become valid again
Release mutex
If something goes wrong in after #2 has begun and before #3 has finished, the object may be left in a state which does not satisfy its invariants. Since the proper pattern is to release a mutex before disposing it, the fact that code disposes a mutex without releasing it implies that something went wrong somewhere. As such, it may not be safe for code to enter the mutex (since it hasn't been released), but there's no reason to wait for the mutex to be released (since--having been disposed--it never will be). Thus, the proper course of action is to throw an exception.
A pattern which is somewhat nicer than the one implemented by the .NET mutex object is to have the "acquire" method return an IDisposable object which encapsulates not the mutex, but rather a particular acquisition thereof. Disposing that object will then release the mutex. Code can then look something like:
using(acq = myMutex.Acquire())
{
... stuff that examines but doesn't modify the guarded resource
acq.EnterDanger();
... actions which might invalidate the guarded resource
... actions which make it valid again
acq.LeaveDanger();
... possibly more stuff that examines but doesn't modify the resource
}
If the inner code fails between EnterDanger and LeaveDanger, then the acquisition object should invalidate the mutex by calling Dispose on it, since the guarded resource may be in a corrupted state. If the inner code fails elsewhere, the mutex should be released since the guarded resource is in a valid state, and the code within the using block won't need to access it anymore. I don't have any particular recommendations of libraries implementing that pattern, but it isn't particularly difficult to implement as a wrapper around other kinds of mutex.
We need to understand more then .net to know what is going on the start of the MSDN page gives the first hint that someone “odd” is going on:
A synchronization primitive that can also be used for interprocess
synchronization.
A Mutex is a Win32 “Named Object”, each process locks it by name, the .net object is just a wrapper round the Win32 calls. The Muxtex itself lives within the Windows Kernal address space, not your application address space.
In most cases you are better off using a Monitor, if you are only trying to synchronizes access to objects within a single process.
If you need to garantee that the mutex is released switch to a try catch finally block and put the mutex release in the finally block. It is assumed that you own and have a handle for the mutex. That logic needs to be included before release is invoked.
Reading the documentation for ReleaseMutex, it seems the design decision was that a Mutex should be released consciously. if ReleaseMutex isn't called, it signifies an abnormal exit of the protected section. putting the release in a finally or dispose, circumvents this mechanism. you are still free to ignore the AbandonedMutexException, of course.
Be aware: The Mutex.Dispose() executed by the Garbage collector fails because the garbage collection process does not own the handle according Windows.
Dispose depends on WaitHandle to be released. So, even though using calls Dispose, it won't go into affect until the the conditions of stable state are met. When you call ReleaseMutex you're telling the system that you're releasing the resource, and thus, it is free to dispose of it.
For the last question.
Is there any benefit to putting Mutex in a using block? Or, should I just new up a Mutex instance, wrap it in a try/catch, and call ReleaseMutex() within the finally block (Basically implementing exactly what I thought Dispose() would do)
If you don't dispose of the mutex object, creating too many mutex objects may encounter the following issue.
---> (Inner Exception #4) System.IO.IOException: Not enough storage is available to process this command. : 'ABCDEFGHIJK'
at System.Threading.Mutex.CreateMutexCore(Boolean initiallyOwned, String name, Boolean& createdNew)
at NormalizationService.Controllers.PhysicalChunkingController.Store(Chunk chunk, Stream bytes) in /usr/local/...
The program uses the named mutex and runs 200,000 times in the parallel for loop. Adding using statement resolves the issue.
Related
I have a Wrapper<T> where T : class that wraps around my objects. I store WeakReference<Wrapper<T>> in a ConcurrentDictionary, to implement weakly-referenced thread-safe cache for immutable objects that gets automatically cleaned up when memory is required for something else. I need to call ConcurrentDictionary.TryRemove in the Wrapper destructor to free the weak references in the dictionary that no longer point to a valid object.
It is well-known that we should not use any locking inside destructors because of the risk of dead-lock. So I wonder, can I use ConcurrentDictionary.TryRemove safely in a destructor? I am afraid it might have been implemented using SpinLock or some other tool and thus still presents a risk of dead-lock when used in destructor.
You can see the implementation of the ConcurrentDictionary at this location and the TryRemove implementation uses 'lock(...)'.
What you could do inside the destructor is use the thread pool to perform the removal of the item from the dictionary. You would still need to mark the wrapper instance as no longer valid, so that if a call is made to any of its public methods between the finalizer running and the thread pool removing it, you could detect this and reject the call.
So the reason you DON'T want to use locking in a destructor is due to the fact that the destructor might be called by a FinalizerWorker in a sperate thread while stopping execution on all threads.
Thus, if one thread is in the middle of a ConcurrencyDicitonary operation when the FinalizerWorker is kicked off you might deadlock if the destructor tries to lock the ConcurrencyDictionary (this can be a very difficult to reproduce deadlock).
A spin lock wont help you because if ANY currently executing thread has the ConcurrencyDictionary locked or the Spinner variable locked it WILL NOT release it until the FinalizerWorker completes, which it wont because it will spin/lock forever.
You'r main options here is to implement the IDisposable interface with a SuppressFinalize(this) call, since your object will suppress the Finalizer worker no deadlock can occure and ConcurrencyDictionary operations ARE SAFE !
Thus if you pre-empt Finalizer using object.Dispose() you should be safe use ConcurrencyDictionary, but otherwise DO NOT use any types of locks in your Finalizer Dispose(false) call or you will deadlock at some point.
// Design pattern for a base class.
public class Base: IDisposable
{
private bool disposed = false;
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
//Disposing outside the FinalizerWorker (SAFE)
if (disposing)
m_pDictionary.TryRemove(this);
disposed = true;
}
}
// Use C# destructor syntax for finalization code.
~Base()
{
// Simply call Dispose(false).
Dispose (false);
}
The answers on here are leading you astray. Using locks in a destructor/finalizer is discouraged because it can easily lead to deadlocks, especially when implemented "manually" instead of using a concurrent collection, but sometimes it is necessary. Even on "stop the world" GC implementations finalizers run on a separate finalizer thread that chugs along concurrently with your application.
First thing is first though - it is VERY RARE that what you are suggesting is the ideal way of implementing your desired functionality, to the point where I am quite confident it isn't. To start, WeakReferences are not suitable for use in caching because they get collected far more often than just when "memory is needed". A proper cache implementation monitors memory levels with strong references and releases them as needed when memory usage is too high.
Even in implementations like a WeakValueDictionary where you don't want the collection holding onto the value if it can be collected, the implementation still doesn't receive object collection notifications. Instead you just remove the entry whenever you stumble upon one that was collected, or you scan the entire collection for dead entries every X operations, or every Y seconds, etc.
That said, if you do run into a situation where you NEED to do something when an object is collected, you can use concurrent collections just fine.
Assuming you don't do anything silly, queuing up an ID in a notification queue or removing an item from a concurrent dictionary is safe because those operations are fast and block for only a very short period of time and your application is not blocked while your finalizers run.
It's something you should avoid as much as possible, but sometimes it's the best and only way to implement something. Just make sure that the lock is fast and used as minimally as possible, and not part of any multi-level locking schemes that are easy to accidentally get wrong and deadlock.
When you look at C#'s Monitor class, the one used under the hood of the lock keyword, you'll find that in its implementation you have a condition variable and a mutex. The mutex is acquired by a new thread entering, if not already acquired by another thread, and then it goes on to check the condition variable, if it is true, the thread can proceed, if it isn't true, then it gets put on the condition variable's thread sleep queue, in order to be woken when the condition variable becomes true again.
Now, why does Monitor need a condition variable? What condition does it check? I have read through wikipedia's article on Monitor and I haven't been able to deduce what condition it would wait on?
Its not something specified by the user of lock or Monitor, but some internal variable. Seeing that the object taking as argument by lock, is supposedly only for identifying the lock.
Is this just like using a AutoResetEvent and a Mutex and acquiring a lock on the Mutex and then seeing if the AutoResetEvent is set to signalled?
I'm not sure I get why Monitor needs a condition variable, when a thread waits to acquire a mutex, doesn't it also get woken up when the mutex is released? (The OS scheduler being the one that probably does the waking)
I'm hoping that this makes sense, and that someone can find the gap in my understanding.
This is an overload of the Monitor.Enter method introduced in CLR 4.0 to correct a subtle vulnerability.
This is explained in this website.
Monitor.Enter (_locker);
try
{
if (_val2 != 0) Console.WriteLine (_val1 / _val2);
_val2 = 0;
}
finally { Monitor.Exit (_locker); }
Consider the (unlikely) event of an exception being thrown within the implementation of Monitor.Enter, or between the call to Monitor.Enter and the try block (due, perhaps, to Abort being called on that thread — or an OutOfMemoryException being thrown). In such a scenario, the lock may or may not be taken. If the lock is taken, it won’t be released — because we’ll never enter the try/finally block. This will result in a leaked lock.
To avoid this danger, CLR 4.0’s designers added the following overload to Monitor.Enter
TL;DR -- Is it ever appropriate to execute business logic in IDisposable.Dispose?
In my search for an answer, I read through the question: Is it abusive to use IDisposable and "using" as a means for getting "scoped behavior" for exception safety? It came very close to addressing this issue, but I'd like to attack it dead on. I recently encountered some code that looked like this:
class Foo : IDisposable
{
public void Dispose()
{
ExecuteSomeBusinessBehavior();
NormalCleanup();
}
}
and is used in a context such as:
try
{
using (var myFoo = new Foo())
{
DoStuff();
foo.DoSomethingFooey();
...
DoSomethingElse();
Etc();
}
}
catch (Exception ex)
{
// Handle stuff
}
Upon seeing this code I immediately began to itch. Here's what I see when I look at this code:
First, looking at just the usage context, it's not remotely apparent that actual business logic, not just cleanup code, will be executed when the code leaves the using scope.
Second, if any of the code within the "using" scope throws an exception, the business logic in the Dispose method will still execute and does so before the Try/Catch can handle the exception.
My questions to the StackOverflow community are these: Does it ever make sense to put business logic in the IDisposable.Dispose method? Is there a pattern that achieves similar results without making me itch?
(Sorry, this is more of a comment, but it exceeds the comment length limit.)
Actually, there is an example in the .NET framework where IDisposable is used to create a scope and do useful work when disposing: TransactionScope.
To quote from TransactionScope.Dispose:
Calling this method marks the end of the transaction scope. If the TransactionScope object created the transaction and Complete was called on the scope, the TransactionScope object attempts to commit the transaction when this method is called.
If you decide to take that route, I would suggest that
you make it blatantly obvious that your object creates a scope, e.g., by calling it FooScope instead of Foo and
you think very hard about what should happen when an exception causes the code to leave your scope. In TransactionScope, the pattern of calling Complete at the end of the block ensures that Dispose can distinguish between the two cases.
The real meaning of IDisposable is that an object knows of something, somewhere which has been put into a state that should be cleaned up, and it has the information and impetus necessary to perform such cleanup. Although the most common "states" associated with IDisposable are things like files being open, unmanaged graphic objects being allocated, etc. those are only examples of uses, and not a definition of "proper" use.
The biggest issue to consider when using IDisposable and using for scoped behavior is that there is no way for the Dispose method to distinguish scenarios where an exception is thrown from a using block from those where it exits normally. This is unfortunate, since there are many situations where it would be useful to have scoped behavior which was guaranteed to have one of two exit paths depending upon whether the exit was normal or abnormal.
Consider, for example, a reader-writer lock object with a method that returns an IDisposable "token" when the lock is acquired. It would be nice to say:
using (writeToken = myLock.AcquireForWrite())
{
... Code to execute while holding write lock
}
If one were to manually code the acquisition and release of the lock without a try/catch or try/finally lock, an exception thrown while the lock was held would cause any code that was waiting on the lock to wait forever. That is a bad thing. Employing a using block as shown above will cause the lock to be released when the block exits, whether normally or via exception. Unfortunately, that may also be a bad thing.
If an unexpected exception is thrown while a write-lock is held, the safest course of behavior would be to invalidate the lock so that any present or future attempt to acquire the lock will throw an immediate exception. If the program cannot usefully proceed without the locked resource being usable, such behavior would cause it to shut down quickly. If it can proceed e.g. by switching to some alternate resource, invalidating the resource will allow it to get on with that much more effectively than would leaving the lock uselessly acquired. Unfortunately, I don't know of any nice pattern to accomplish that. One could do something like:
using (writeToken = myLock.AcquireForWrite())
{
... Code to execute while holding write lock
writeToken.SignalSuccess();
}
and have the Dispose method invalidate the token if it's called before success has been signaled, but an accidental failure to signal the success could cause the resource to become invalid without offering indication as to where or why that happened. Having the Dispose method throw an exception if code exits a using block normally without calling SignalSuccess might be good, except that throwing an exception when it exits because of some other exception would destroy all information about that other exception, and there's no way Dispose can tell which method applies.
Given those considerations, I think the best bet is probably to use something like:
using (lockToken = myLock.CreateToken())
{
lockToken.AcquireWrite(Describe how object may be invalid if this code fails");
... Code to execute while holding write lock
lockToken.ReleaseWrite();
}
If code exits without calling ReleaseWrite, other threads that try to acquire the lock will receive exceptions that include the indicated message. Failure to properly manually pair the AcquireWrite and ReleaseWrite will leave the locked object unusable, but not leave other code waiting for it to become usable. Note that an unbalanced AcquireRead would not have to invalidate the lock object, since code inside the read would never put the object into an invalid state.
Business logic code should never be written in any circumstances to Dispose method reason is, you are relying on a unreliable path. What if user does not call your dispose method? You missed to call a complete functionality ? What if there was an exception thrown in the method call of your dispose method? And why would you perform a business operation when user is asking to dispose the object itself. So logically, technically it should not be done.
I'm currently reading Introduction to Rx, by Lee Campbell, and it has a chapter called IDisposable, where he explicitly advocates taking advantage of the integration with the using construct, in order to "create transient scope".
Some key quotations from that chapter:
"If we consider that we can use the IDisposable interface to effectively create a scope, you can create some fun little classes to leverage this."
(...see examples below...)
"So we can see that you can use the IDisposable interface for more than just common use of deterministically releasing unmanaged resources. It is a useful tool for managing lifetime or scope of anything; from a stopwatch timer, to the current color of the console text, to the subscription to a sequence of notifications.
The Rx library itself adopts this liberal usage of the IDisposable interface and introduces several of its own custom implementations:
BooleanDisposable
CancellationDisposable
CompositeDisposable
ContextDisposable
MultipleAssignmentDisposable
RefCountDisposable
ScheduledDisposable
SerialDisposable
SingleAssignmentDisposable"
He gives two fun little examples, indeed:
Example 1 - Timing code execution. "This handy little class allows you to create scope and measure the time certain sections of your code base take to run."
public class TimeIt : IDisposable
{
private readonly string _name;
private readonly Stopwatch _watch;
public TimeIt(string name)
{
_name = name;
_watch = Stopwatch.StartNew();
}
public void Dispose()
{
_watch.Stop();
Console.WriteLine("{0} took {1}", _name, _watch.Elapsed);
}
}
using (new TimeIt("Outer scope"))
{
using (new TimeIt("Inner scope A"))
{
DoSomeWork("A");
}
using (new TimeIt("Inner scope B"))
{
DoSomeWork("B");
}
Cleanup();
}
Output:
Inner scope A took 00:00:01.0000000
Inner scope B took 00:00:01.5000000
Outer scope took 00:00:02.8000000
Example 2 - Temporarily changing console text color
//Creates a scope for a console foreground color. When disposed, will return to
// the previous Console.ForegroundColor
public class ConsoleColor : IDisposable
{
private readonly System.ConsoleColor _previousColor;
public ConsoleColor(System.ConsoleColor color)
{
_previousColor = Console.ForegroundColor;
Console.ForegroundColor = color;
}
public void Dispose()
{
Console.ForegroundColor = _previousColor;
}
}
Console.WriteLine("Normal color");
using (new ConsoleColor(System.ConsoleColor.Red))
{
Console.WriteLine("Now I am Red");
using (new ConsoleColor(System.ConsoleColor.Green))
{
Console.WriteLine("Now I am Green");
}
Console.WriteLine("and back to Red");
}
Output:
Normal color
Now I am Red
Now I am Green
and back to Red
Is there anything wrong with using lock with a try block? I remember reading somewhere that we should always try to put minimum amount of code within try block and lock itself internally uses a try-finally block, do you guys see something wrong here.I need to deal with the fact that the code within that lock block can throw exception
try
{
lock(syncblk)
{
// do some processing
}
}
catch(Exception e)
{
// do something with exception
}
I need to deal with the fact that the code within that lock block can throw exception
And there's your problem. That's a terrible situation to be in.
Why are you locking in the first place? Usually the reason why you lock something is because you want to implement the following logic:
lock the door
make a mess
clean it up
unlock the door
If you do that, then no one who honours the locked door ever sees the mess.
For example, you might want to swap values of variables "left" and "right" in a threadsafe manner, so you:
take the lock
read the left variable into tempLeft
read the right variable into tempRight
write tempLeft into right
we just made a mess; the original value of 'right' has gone missing
write tempRight into left
we've cleaned up the mess, all is well with the world again
release the lock
Now suppose an exception is thrown after the mess is made. What happens? We jump straight to the unlock, leaving the mess for another thread to see.
That's why you should never throw an exception inside a lock; it completely defeats the purpose of the lock! The whole point of a lock is to ensure that state is always observed to be consistent by all threads except the one responsible for cleaning up the mess.
If you have an exception that can be thrown from inside a lock, the best thing to do is to get out of that horrible situation. If you can't do that, then make sure that you can either (1) destroy the process utterly as soon as the exception escapes the lock, so that the mess you made cannot cause data loss or other harm -- do a FailFast and nuke the process from orbit, it's the only way to be sure -- or (2) write rollback code that undoes whatever operation you were attempting before the lock is exited; that is, clean up the mess back to the original state.
If the latter is your strategy then don't put the try block outside the lock; it's useless there because the instant control leaves the lock via the exception another thread can be crashing and dying because of the mess you left exposed to it. Put the try that deals with the exception inside the lock:
lock(whatever)
{
try
{
MakeAMess();
}
finally
{
CleanItUp();
// Either by completing the operation or rolling it back
// to the pre-mess state
}
}
If you have strong reliability requirements then dealing with locked critical sections which can throw exceptions is an extremely difficult programming task best left to experts; you might consider using a constrained execution region if you find yourself in this situation a lot.
I think you can do it your way but here is the MSDN description on lock for your information. Please refer to http://msdn.microsoft.com/en-us/library/ms173179.aspx for more info.
Using the lock (C#) or SyncLock
(Visual Basic) keyword is generally
preferred over using the Monitor class
directly, both because lock or
SyncLock is more concise, and because
lock or SyncLock insures that the
underlying monitor is released, even
if the protected code throws an
exception. This is accomplished with
the finally keyword, which executes
its associated code block regardless
of whether an exception is thrown.
So I am not sure what kind of exception you are referring to but if you concern is that you may not be able to release the lock because of exception, you do not have to worry about it.
you can always use the longer syntax like this:
System.Threading.Monitor.Enter(x);
try {
...
}
catch(Exception e)
{
}
finally {
System.Threading.Monitor.Exit(x);
}
I'm working on some big multi threaded project, now yesterday I had a deadlock (my first one ever), and I traced it by adding a Console.WriteLine("FunctionName: Lock on VariableName") and Console.WriteLine("FunctionName: Unlocking VariableName"). Adding all those was quite some work.
First of all, the program has a main loop that runs 2 times per second, that loop pulses some other threads to complete their work after the main loop has processed. Now what happened was that I had one thread in wait state to be pulsed, when it was pulsed it called another method that'd also wait to get pulsed, but the pulse already happened, and the thread won't pulse again until the action is actually completed.
Now what I want to do is override the Monitor.Enter and Monitor.Exit functions, without wrapping them in a class.
I've heard a lot about Reflection, but I have no idea how to apply it for this purpose, I know the easiest way to achieve it all is by just using a wrapper class, but then the lock keyword won't work anymore, and I'd have to convert all locks into Monitor.Enter try { } finally { Monitor.Exit }, that's huge amount of work.
So my question: How to override the Monitor.Enter and Monitor.Exit functions, while keeping access to the base function to do the actual lock?
And if that's impossible: How to override the lock statement to call my wrapper class instead of the Monitor.Enter and Monitor.Exit functions?
EDIT FOR CLARITY:
I request this just for allowing me to log when the locks happen, to make the debugging process easier, that also means I don't want to create my own locking mechanism, I just want to log when a lock is established and when it's released.
The close will also not be executed most of the time, only when I come across a threading problem.
It sounds like you're looking for lock helpers. Jon Skeet's MiscUtil has some:
http://www.yoda.arachsys.com/csharp/miscutil/usage/locking.html
The idea is that you replace your lock statements with using statements and thus preserve the try-finally structure:
class Example
{
SyncLock padlock = new SyncLock();
void Method1
{
using (padlock.Lock())
{
// Now own the padlock
}
}
void Method2
{
using (padlock.Lock())
{
// Now own the padlock
}
}
}
With regards to deadlock prevention, the library offers a specialized ordered lock:
class Example
{
OrderedLock inner = new OrderedLock("Inner");
OrderedLock outer = new OrderedLock("Outer");
Example()
{
outer.InnerLock = inner;
}
}
Of course, you could extend Jon's helpers, or simply create your own (for logging purposes, etc). Check out the link above for more information.
Don't do it! That sounds bonkers ;-)
A deadlock occurs when 2 (or more) threads are all waiting to simultaneously hold 2 (or more) locks. And each thread gets a lock and waits for the other one.
You can often redesign your code so each thread only requires a single lock - which makes deadlock impossible.
Failing that, you can make a thread give up the first lock if it can't acquire the second lock.
That's a very bad idea. I never had to override Monitor.Enter / Exit or lock to overcome a deadlock. Please consider redesigning your code!
For example, use ManualResetEvent for the pulsing.