Mutually Exclusive C# Method

  • Thread starter Thread starter Paul Allan
  • Start date Start date
P

Paul Allan

I am creating a VS 2005, C# Assembly.

I want to create an assembly with a method that can only be executed by one
thread across process at any given time (so that it's totally mutually
exclusive).

I have played around with creating a singleton class, that uses the
"System.Threading.Semaphore" class, but it does not seem to work.

Any help or direction with this would be much appreciated!

Paul.
 
Paul,

I assume you can't accomplish this with a local lock on a singleton? If
you're worried about multiple instances of your assembly (i.e. -- more
than one process running myassembly.dll), that's a solved problem. If
the standard locking mechanism isn't enough, you can query the
framework to tell you the current executing thread and compare that to
a static "this thread is allowed" register.


Stephan
 
Hi Stephan.

Thanks for your response.

Am I right in saying that a local lock in a singleton will not prevent
access to threads from different processes (will it only synchronize threads
in the current process)? In a singleton, will the method always execute
under the same thread no matter where it is called from?

Do I even need a singleton class? Will the System.Threading.Semaphore class
(in multiple instances of the object containing the method) synchronize
access to the method from multiple threads across processes?

Am I even using the right approach?

Paul.
 
Paul said:
I am creating a VS 2005, C# Assembly.

I want to create an assembly with a method that can only be executed
by one thread across process at any given time (so that it's totally
mutually exclusive).

I have played around with creating a singleton class, that uses the
"System.Threading.Semaphore" class, but it does not seem to work.

Any help or direction with this would be much appreciated!

If you truly need to limit execution to a single thread across all processes
(not just a single process), then you want to use a named mutex
(System.Threading.Mutex). You could do it using a semaphore as well (with a
max count of 1), but it's easier using a mutex and the system provides some
automatic recovery for a mutex (if the thread that owns a mutex terminates
without releasing it, the system automatically releases the mutex and
returns a distinguished return value to the next waiter. If it didn't do
that, all other waiters would be stuck forever).

If you could post the code that you tried, I'm sure I or someone else will
be able to see where you mis-stepped. Note that you must use Named mutex
(or semaphore) to get cross-process synchronization (barring some scheme by
which you duplicate handles and communicate them between the processes,
which doesn't seem like what you'd be wanting).

-cd
 
If it's a single process, create a static Syncronization Object the is
private to the method you need to serialize. Something along these lines
should do it for single process synchroinzation.

private static SynchronizationContext so = new SynchronizationContext;
Object foo()
{
lock(so) {
// This code can only be entered by one thread at a time
return new Object();
}
}
}


Mike.
 
Hi Michael,

You shouldn't lock on a SynchronizationContext object. The purpose of that
class is to support multi-threaded synchronization out of the normal Control
execution context, such as in library code, but I highly doubt that its
author(s) intended it to be used simply as an object to lock on. You're much
better off locking on a new object:

private static readonly object sync = new object();

object foo()
{
lock (sync)
{
return new object();
}
}
 
Carl.

Thanks for getting back to me with your valuable insight.

Below is my singleton class where I tried to use the
System.Threading.Semaphore class.

I just Googled the System.Threading.Mutex class, and I think your right.

How do I use a named Mutex in my singleton class?
Do I need a singleton class or will a named mutex work across many instances
of my class?

Regards,

Paul.

------------------------------------------------------------------------------------------
using System;
using System.Threading;

namespace MyNamespace

{

public sealed class SyncronizedMethodClass

{

private SyncronizedMethodClass()

{

}

private static readonly SyncronizedMethodClass Instance = new
SyncronizedMethodClass();

private static Semaphore semaphore = new Semaphore(1,1);

public static string ExecuteThreadSyncedMethod(string source)

{

string ReturnValue;

semaphore.WaitOne();

ReturnValue = Instance.MyUniqueMethod();

semaphore.Release();

return ReturnValue;

}

private string MyUniqueMethod()

{

string MyValue=string.Empty;

//Processing code removed...

return MyValue;

}

}

}
 
Paul Allan said:
Carl.

Thanks for getting back to me with your valuable insight.

Below is my singleton class where I tried to use the
System.Threading.Semaphore class.

I just Googled the System.Threading.Mutex class, and I think your right.

How do I use a named Mutex in my singleton class?

Just replace System.Threading.Semaphore with System.Threading.Mutex and
replace the call to .Release() with a call to .ReleaseMutex(). You need to
call one of the constructors that takes a name in order to create a named
mutex. It you don't create a named mutex, you'd need to communicate the
handle to other processes in order to get cross-process synchronization.
Do I need a singleton class or will a named mutex work across many
instances of my class?

You don't really need a singleton, but it's not a bad design. You can
actually create as many System.Threading.Mutex objects as you wish and as
long as they all refer to the same named mutex, they all share a single
synchronization context across all threads and processes.

Why do you believe that you need to synchronize access across multiple
processes? I'm guessing that you're probably writing to some shared state
(e.g. a log file). If that's the case, you also need to make sure to flush
writes to the shared resource (e.g. by calling System.IO.Stream.Flush())
while you own the mutex to make sure that all output is actually written
before leaving the synchronized block.

There's usually a better solution than global synchronization though - it's
quite expensive. So if you can provide some details of the kind of
operation you're trying to protect, someone may well be able to come up with
a better solution.

-cd
 
Carl.

I really appreciate your help.



The reason I am doing this has to do with security, so I cannot really go
into detail.



If I were writing to a shared log file, off the top of my head, I would
probably use Microsoft Message Queuing (guaranteed delivery). Would using a
Mutex be better than this approach?



Paul.
 
Paul said:
Carl.

I really appreciate your help.

The reason I am doing this has to do with security, so I cannot
really go into detail.

OK. Just keep in mind - security through obscurity is false hope at best.
If I were writing to a shared log file, off the top of my head, I
would probably use Microsoft Message Queuing (guaranteed delivery). Would
using a Mutex be better than this approach?

Yes and no. Using a queue has definite performance advantages since you
don't block other writers while one process is writing, but it's a bit more
complex to set up. You'll generally need a dedicated writer process (likely
a windows service) in such a scenario, but it works well.

-cd
 
The reason I am doing this has to do with security, so I cannot really go
into detail.

Heh... well good luck with that. You know that anyone can decompile a
..Net assembly and get at the original code very easily right? Even if
you obfuscate it, someone with enough time can figure your code out.

Andy
 
Back
Top