Using Mutexes for interprocess synchronisation - getting AME - c#

I don't understand this behavior:
static Mutex Mut;
static void Main(string[] args)
{
try
{
Mut = System.Threading.Mutex.OpenExisting("testmut");
}
catch
{
Mut = new Mutex(true, "testmut");
}
Mut.WaitOne();
Thread.Sleep(4000);
Mut.ReleaseMutex();
}
Starting two instances of this application simultaneously will cause the second application to get an Abandoned Mutex Exception after the first process terminates. Why? I did explicitly release the mutex before terminating there in the first process.

Okay, the problem was simple. I actually gained Mutex ownership twice in the first process, first by calling Mut = new Mutex(true, "testmut"); (the true flag grants the caller ownership of the Mutex), and then doing a WaitOne(). Obviously, since I only freed it once in the end, I was getting an AM Exception.

Related

Mutex and Windows Phone 8.1 Silverlight

I want to prevent my Background Process from performing an action if the app is open in the foreground. I found a similar question posed here, but I can't get it to work for me. When my Background Process checks the Mutex, it is never already in existence. When the foreground app starts I create a Mutex like so:
public void Application_Launching(object sender, LaunchingEventArgs e)
{
var myMutex = new Mutex(false, "MUTEX_NAME");
}
I release it when the foreground app closes:
private void Application_Closing(object sender, ClosingEventArgs e)
{
var myMutex = new Mutex(false, "MUTEX_NAME");
myMutex.ReleaseMutex();
}
In the Background Process I have the following check:
bool IsMutexLocked()
{
var myMutex = new Mutex(false, "MUTEX_NAME");
return myMutex.WaitOne(100);
}
I'm assuming here that WaitOne returns true if "MUTEX_NAME" doesn't exist, or it does exist but gets released after 100ms. I've also tried using the out createdNew in the Mutex constructor, and the static methods OpenExistingand TryOpenExisting but to no avail.
You are not locking your mutex in main app, you just create it (also without ownership). You can either create Mutex with initial ownership or call WaitOne() when needed. Some more help at Joe Alabhari's blog.
public void Application_Launching(object sender, LaunchingEventArgs e)
{
var myMutex = new Mutex(true, "MUTEX_NAME");
// or call myMutex.WaitOne() // here maybe some timeout handling
}
Also I don't think that holding a mutex until the app is closed is a good practise - lock the mutex only when you really need to (for example access to common file). If you really want to try this, create a global mutex instance upon launching, then release it upon closing, but without obtaining it again, just use previous instance.
Look out for couple of things - don't leave abandoned mutexes, look out so it's not garbage collected, release it when needed. There are plenty of posts about this synchronization object, here you have a good pattern.

Mutex - TryOpenExisting vs new one

I'm thinking about Mutexes and I need some clarification about them. Should I try to open existing Mutex or create new one (of course both with the same name). Example of code:
First attempt - try open existing one:
private void AttemptOne()
{
Mutex myMutex;
if (!Mutex.TryOpenExisting("Mutex Name", out myMutex))
myMutex = new Mutex(false, "Mutex Name");
try
{
myMutex.WaitOne(3000);
// code
}
catch { }
finally
{
myMutex.ReleaseMutex();
// myMutex.Dispose(); - should I call that or it will be called automatically when returning from method?
}
}
Second attempt - create new Mutex:
private void AttemptTwo()
{
using (Mutex mutex = new Mutex(false, "Mutex Name"))
{
try
{
mutex.WaitOne(3000);
// code
}
catch { }
finally { myMutex.ReleaseMutex(); }
}
}
I have some questions, which bother me:
which attempt to use?
Let assume that I have a background process with created Mutex, and at the same time Main process tries to do some work, which should be blocked until backgorund process finishes. If background process created its own Mutex, should I try to open it?
Or create new Mutex in Main thread with the same name?
What is the difference between those attempts?
should I call Dispose() in first Attempt?
Or just assume that Mutex will be disposed when method returns? Will it be disposed then?
I assume that in second attempt Mutex will be Disposed (as its IDisposable) when using() ends. Am I right?
If you're planning to create the mutex if it doesn't exist anyway, then just go ahead and use the second method.
If you're going for a different behavior based on the existence of the mutex, then you should use TryOpenExisting to check if it exists.
As for your other questions:
Yes, you should call the Dispose or Close method on the mutex when you're done with it. In order to allow the operating system to destroy it once it's not in use.
Yes, using would call the Mutex object Dispose method.
I think you shouldn't use named mutex to synchronize threads in a single process. It's better to share a mutex (or semaphore) object between this threads (in a local variable or in a class field for example). So use named mutex to make process synchronization(for example running only one copy of the application).
About your questions. TryOpenExisting() represent a common pattern TryXxx and provide you opportunity to check the result of an operation without exceptions. Although there are some constructor overloads that have out createdNew boolean parameter you must declare another variable for this what is ugly. Your second variant means that you don't care about whether you have existing mutex or just create a new.
Calling Dispose() (or put the object into using) is always usefull practice. If you use named mutex like in your code all will be fine after disposing. But if you dispose a shared mutex variable (like I advice) in one thread all other threads which waits this mutex will fall with an exception. In this case you should dispose mutex only when you realy sure that you have no needs in it.
As you can see answers on your questions depends on the specific situation.

unable to synchronize two threads

If I do:
ConsoleApp1:
bool mutexCreated;
var mutex = new Mutex(true, "MemoryMappedFileMutex", out mutexCreated);
Console.Write("Run Console App2 then press enter");
Console.Read();
// do work
Thread.Sleep(5000);
mutex.ReleaseMutex(); // makes console app 2 to stop waiting
ConsoleApp2
var mutex = Mutex.OpenExisting("MemoryMappedFileMutex");
mutex.WaitOne();
// continue executing once console app 1 releases mutex
Everything works great. I have to start consoleApp1 first for this algorithm to work though.
Now my qestion is I will like consoleApp2 to act as the server. Therefore I will like to start that application first. The problem is that if I do:
bool mutexCreated;
var mutex = new Mutex(true, "MemoryMappedFileMutex", out mutexCreated);
mutex.WaitOne(); // <------ mutex will not wait why????
if I do mutex.WaitOne() that thread will not wait. In other words I want to start consoleApp2 first and have that application wait until I signal the mutex somehow on console application 1....
In your server app, try calling the constructor with false as the first parameter, so that the calling thread will not own the mutex initially.
Waiting on a Mutex from the owning thread does not block, and you specified true as the first Mutex constructor arg, which indicates it gets created already owned by the current thread.

Creating a lock for a console application

I have a console application which will be initiated by different batch files set up windows task scheduler. I would like to queue these commands or have some sort of a lock mechanism in my application that would have all the commands waiting on a queue, so that only one command runs at a time. I was thinking about doing some sort of a file lock, but i cant get my head wrapped around to how would it work for queuing commands. I just need some sort of direction.
For inter-process synchronization, you may use a Mutex instance representing a named system mutex.
// Generate your own random GUID for the mutex name.
string mutexName = "afa7ab33-3817-48a4-aecb-005d9db945d4";
using (Mutex m = new Mutex(false, mutexName))
{
// Block until the mutex is acquired.
// Only a single thread/process may acquire the mutex at any time.
m.WaitOne();
try
{
// Perform processing here.
}
finally
{
// Release the mutex so that other threads/processes may proceed.
m.ReleaseMutex();
}
}
Look for Semaphore object.
_resultLock = new Semaphore(1, 1, "GlobalSemaphoreName");
if (!_resultLock.WaitOne(1000, false))
{
// timeout expired
}
else
{
// lock is acquired, you can do your stuff
}
You can always put your timeout to Infinite, but it is practical to get control over the program flow from time to time and be able to abort gracefully.

Is this the proper use of a mutex?

I have a situation where I might have multiple instances of a program running at once, and it's important that just one specific function not be executing in more than one of these instances at once.
Is this the proper way to use a mutex to prevent this from happening?
lock (this.GetType()) {
_log.Info("Doing Sync");
DoSync();
_log.Info("Sync Completed");
}
You said multiple instances of one application, so we're talking about two program.exe's running, right? The lock statement won't lock across multiple programs, just within the program. If you want a true Mutex, look at the System.Threading.Mutex object.
Here is a usage example:
bool createdNew;
using (Mutex mtx = new Mutex(false, "MyAwesomeMutex", out createdNew))
{
try
{
mtx.WaitOne();
MessageBox.Show("Click OK to release the mutex.");
}
finally
{
mtx.ReleaseMutex();
}
}
The createdNew variable will let you know whether or not it was created the first time. It only tells you if it has been created, though. If you want to acquire the lock, you need to call WaitOne and then call ReleaseMutex to release it. If you just want to see if you created a Mutex, just constructing it is fine.
TheSeeker is correct.
Jeff Richter's advice in Clr Via C# (p638-9) on locking is to create a private object specifically for the purpose of being locked.
private Object _lock = new Object();
// usage
lock( _lock )
{
// thread-safe code here..
}
This works because _lock cannot be locked by anything outside the current class.
EDIT: this is applicable to threads executing within a single process. #David Mohundro's answer is correct for inter-process locking.

Categories

Resources