I'm trying to create a generic method that accepts a delegate. The sole purpose of the method is to ensure whatever unique code block you pass to it, is only accessed by one thread at a time. I'm pointing out the word unique as unique code blocks can run side by side, duplicate code blocks must run synchronously. Is there a clean pattern to achieve this?
Asked
Active
Viewed 281 times
-1
-
use mutex, lock, or sophomores ? What have you tried exactly ? – Mekap Jun 22 '16 at 06:40
-
I've tried all of them. I'm really looking for the right pattern mainly based on the requirements. – Captain Kirk Jun 22 '16 at 16:59
-
@Mekap: You meant semaphore? – Jim Mischel Jun 22 '16 at 18:19
-
@JimMischel Yes. Exactly :$ – Mekap Jun 22 '16 at 19:55
-
How do you identify "unique code"? Show us some examples. – Jim Mischel Jun 22 '16 at 20:50
2 Answers
2
You can do something like this:
namespace RunSafe
{
// Declare a delegate type
public delegate void RunSafeDelegate();
public class SafeRunner
{
private object _lock = new Object();
public void Runner( RunSafeDelegate runsafe )
{
lock( this._lock )
{
runsafe();
}
}
}
}

Darrin Cullop
- 1,170
- 8
- 14
-
Thanks Dex. Is there a way to enforce the lock only if the code block is the same? I essentially need this to scale so that if a different block of code is coming in, it should deal with that as a separate lock. – Captain Kirk Jun 22 '16 at 16:54
-
1@user1701153 that's not a good way to do it. Code is immutable. It does not have to be protected. Locks protect data, not code. – usr Jun 22 '16 at 17:13
-
@usr Ultimately the code is acting on things that I need to protect. For example one code block I might be passing in would be to get a free tcp port. I want to synchronize that to avoid collisions. Etc. – Captain Kirk Jun 22 '16 at 18:19
-
That will only work if everybody uses the same instance of `SafeRunner`, and then you wouldn't be able to have more than one of them running at a time. – Jim Mischel Jun 22 '16 at 18:20
-
-
Then you're synchronizing for ports, not the code. Create a lock or a "SafeRunner" controlling the port. – usr Jun 22 '16 at 18:55
-
@usr Thanks usr. I can definitely do that and know how to do that. My OP is really to see if I can simplify that kind of design to be more generic. Since I might have 20 things in the code that I need to synchronize i'd like to have a common lock utility that I can say hey, here's some unique code, make sure only one person runs it at a time. Instead of littering the code and putting that effort on other people. – Captain Kirk Jun 22 '16 at 19:14
0
Ultimately Dex Star's code example lead me down the path I was looking for.
If there are any concerns please let me know. I believe this is a solid solution. Note i'm using a named mutex on purpose as there may be multiple processes involved in accessing resources.
// test code
RunSafeDelegate rsd1 = () => { /* some code i need synchronous */ };
RunSafeDelegate rsd2 = () => { /* other code i need synchronous */ };
var util = new UtilityClass();
util.RunSafe(rsd1, "myMutexName1");
util.RunSafe(rsd2, "myMutexName2");
// implementation
public class UtilityClass
{
public delegate void RunSafeDelegate();
public void RunSafe(RunSafeDelegate runSafe, string mutexName)
{
const int WAIT_ONE_TIMEOUT = 30000;
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
var mar = new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow);
var ms = new MutexSecurity();
ms.AddAccessRule(mar);
bool mutexCreated;
using(var mutex = new Mutex(false, mutexName, out mutexCreated, ms))
{
var signalReceived = false;
try
{
try
{
signalReceived = mutex.WaitOne(WAIT_ONE_TIMEOUT, false);
if(!signalReceived)
{
throw new TimeoutException("Exclusive access timeout for mutex: " + mutexName);
}
}
catch(AbandonedMutexException)
{
signalReceived = true;
}
runSafe();
}
finally
{
if(signalReceived)
{
mutex.ReleaseMutex();
}
}
}
}
}

Captain Kirk
- 350
- 6
- 24
-
I'm glad you got what you needed. If you are using Mutexes, they are IDisposable, so you'll want `using ( var mutex = new Mutex(false, mutexName) ) { }` ... Also, since your class no longer has instance members, you can make it, and its methods `static` and avoid having to instantiate it. – Darrin Cullop Jun 23 '16 at 15:44
-
@DexStar Thanks Dex. Greatly appreciate the advice. I've updated my implementation based on your feedback and some great information I found in another post: http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c – Captain Kirk Jun 23 '16 at 16:37