Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a System Mutex in C#

How can I create a system/multiprocess Mutex to co-ordinate multiple processes using the same unmanaged resource.

Background: I've written a procedure that uses a File printer, which can only be used by one process at a time. If I wanted to use it on multiple programs running on the computer, I'd need a way to synchronize this across the system.

like image 936
C. Ross Avatar asked Feb 02 '10 18:02

C. Ross


People also ask

What is mutex in C programming?

A Mutex is a lock that we set before using a shared resource and release after using it. When the lock is set, no other thread can access the locked region of code.

What is mutex example?

Example 4-1 Mutex Lock ExampleThe get_count() function uses the mutex lock to guarantee that the 64-bit quantity count is read atomically. On a 32-bit architecture, a long long is really two 32-bit quantities. Reading an integer value is an atomic operation because integer is the common word size on most machines.

How do you create a mutex in C++?

In C++, we create a mutex by constructing an instance of std::mutex, lock it with a call to the member function lock(), and unlock it with a call to the member function unlock().


2 Answers

You can use the System.Threading.Mutex class, which has an OpenExisting method to open a named system mutex.

That doesn't answer the question:

How can I create a system/multiprocess Mutex

To create a system-wide mutex, call the System.Threading.Mutex constructor that takes a string as an argument. This is also known as a 'named' mutex. To see if it exists, I can't seem to find a more graceful method than try catch:

System.Threading.Mutex _mutey = null;
try
{
    _mutey = System.Threading.Mutex.OpenExisting("mutex_name");
    //we got Mutey and can try to obtain a lock by waitone
    _mutey.WaitOne();
}
catch 
{
    //the specified mutex doesn't exist, we should create it
    _mutey = new System.Threading.Mutex("mutex_name"); //these names need to match.
}

Now, to be a good programmer, you need to, when you end the program, release this mutex

_mutey.ReleaseMutex();

or, you can leave it in which case it will be called 'abandoned' when your thread exits, and will allow another process to create it.

[EDIT]

As a side note to the last sentence describing the mutex that is abandoned, when another thread acquires the mutex, the exception System.Threading.AbandonedMutexException will be thrown telling him it was found in the abandoned state.

[EDIT TWO]

I'm not sure why I answered the question that way years ago; there is (and was) a constructor overload that is much better at checking for an existing mutex. In fact, the code I gave seems to have a race condition! (And shame on you all for not correcting me! :-P )

Here's the race condition: Imagine two processes, they both try to open the existing mutex at the same time, and both get to the catch section of code. Then, one of the processes creates the mutex and lives happily ever after. The other process, however, tries to create the mutex, but this time it's already created! This checking/creating of a mutex needs to be atomic.

http://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.90).aspx

So...

var requestInitialOwnership = false;
bool mutexWasCreated;
Mutex m = new Mutex(requestInitialOwnership, 
         "MyMutex", out mutexWasCreated);

I think the trick here is that it appears that you have an option that you don't actually have (looks like a design flaw to me). You sometimes can't tell if you own the mutex if you send true for requestInitialOwnership. If you pass true and it appears that your call created the mutex, then obviously you own it (confirmed by documentation). If you pass true and your call did not create the mutex, all you know is that the mutex was already created, you don't know if some other process or thread which perhaps created the mutex currently owns the mutex. So, you have to WaitOne to make sure you have it. But then, how many Releases do you do? If some other process owned the mutex when you got it, then only your explicit call to WaitOne needs to be Released. If your call to the constructor caused you to own the mutex, and you called WaitOne explicitly, you'll need two Releases.

I'll put these words into code:

var requestInitialOwnership = true; /*This appears to be a mistake.*/
bool mutexWasCreated;
Mutex m = new Mutex(requestInitialOwnership, 
         "MyMutex", out mutexWasCreated);

if ( !mutexWasCreated )
{
    bool calledWaitOne = false;
    if ( ! iOwnMutex(m) ) /*I don't know of a method like this*/
    {
        calledWaitOne = true;
        m.WaitOne();
    }

    doWorkWhileHoldingMutex();

    m.Release();
    if ( calledWaitOne )
    {
        m.Release();
    }
}

Since I don't see a way to test whether you currently own the mutex, I will strongly recommend that you pass false to the constructor so that you know that you don't own the mutex, and you know how many times to call Release.

like image 167
lmat - Reinstate Monica Avatar answered Sep 28 '22 03:09

lmat - Reinstate Monica


You can use the System.Threading.Mutex class, which has an OpenExisting method to open a named system mutex.

like image 20
Sam Harwell Avatar answered Sep 28 '22 05:09

Sam Harwell