How do I mark a method as not-threadsafe? - c#

Every so often I hit upon this problem and ignore it, but it started gnawing at me today.
private readonly object _syncRoot = new object();
private List<int> NonconcurrentObject { get; } = new List<int>();
public void Fiddle()
{
lock (_syncRoot)
{
// ...some code...
NonconcurrentObject.Add(1);
Iddle();
}
}
public void Twiddle()
{
lock (_syncRoot)
{
// ...some different code...
NonconcurrentObject.Add(2);
Iddle();
}
}
private void Iddle()
{
// NOT THREADSAFE! DO NOT CALL THIS WITHOUT LOCKING ON _syncRoot
// ......lots of code......
NonconcurrentObject.Add(3);
}
I have multiple public methods of a class with some code that is not inherently threadsafe (the List above is a trivial example). I want to use helper methods for the code shared between them (as anyone would), but in splitting off the shared code I'm faced with a dilemma: do I use recursive locking in the helper methods or not? If I do, my code is wasteful and possibly less performant. If I don't (as above), the helper method is no longer threadsafe and open to a nasty race condition if called by some other method in the future.
How can I (elegantly and robustly) signal that a method isn't threadsafe?

You use doc comments.
///<remarks>not thread safe</remarks>

You could use custom attributes to mark methods that are not thread safe.
The advantage over comments is that it gives you options for further processing (via reflection) if you wish to do so at a later date.
public class NotThreadSafe : Attribute
{
//...
}
public class MyClass
{
[NotThreadSafe]
public void MyMethod()
{
//...
}
}

You could add the _Unsafe suffix to your utility methods that are not protected with locks.
Advantages: It reminds you that you are doing dangerous things, and so that you must be extra careful. A small mistake could cost you days of debugging in the future.
Disadvantages: Not very pretty, and can be confused with the unsafe keyword.
private void Iddle_Unsafe()
{
NonconcurrentObject.Add(3);
}
public void Twiddle()
{
lock (_syncRoot)
{
NonconcurrentObject.Add(2);
Iddle_Unsafe();
}
}

Related

Thread safe Singletion static method initialization

I'm implementing a singleton pattern, and need the initialization to be thread safe.
I've seen several ways to do it, like using the double check lock implementation, or other techniques (i.e.: http://csharpindepth.com/articles/general/singleton.aspx)
I wanted to know if the following approach, which is similar to the fourth version in the article, is thread safe. I'm basically calling a method in the static field initializer, which creates the instance. I don't care about the lazyness. Thanks!
public static class SharedTracerMock
{
private static Mock<ITracer> tracerMock = CreateTracerMock();
private static Mock<ITracer> CreateTracerMock()
{
tracerMock = new Mock<ITracer>();
return tracerMock;
}
public static Mock<ITracer> TracerMock
{
get
{
return tracerMock;
}
}
}
Yes, that's thread-safe - although it's not the normal singleton pattern, as there are no instances of your class itself. It's more of a "single-value factory pattern". The class will be initialized exactly once (assuming nothing calls the type initializer with reflection) and while it's being initialized in one thread, any other thread requesting TracerMock will have to wait.
Your code can also be simplified by removing the method though:
public static class SharedTracerMock
{
private static readonly Mock<ITracer> tracerMock = new Mock<ITracer>();
public static Mock<ITracer> TracerMock { get { return tracerMock; } }
}
Note that I've made the field readonly as well, which helps in terms of clarity. I generally stick trivial getters all on one line like this too, to avoid the bulk of lots of lines with just braces on (7 lines of code for one return statement feels like overkill).
In C# 6, this can be simplified even more using a readonly automatically implemented property:
public static class SharedTracerMock
{
public static Mock<ITracer> TracerMock { get; } = new Mock<ITracer>();
}
Of course, just because this property is thread-safe doesn't mean that the object it returns a reference to will be thread-safe... without knowing about Mock<T>, we can't really tell that.

Guard object in C#

In C++, it's fairly easy to write a Guard class which takes a reference to a variable (usually a bool) and when the instance object exits scope and gets destructed, the destructor resets the variable to the original value.
void someFunction() {
if(!reentryGuard) {
BoolGuard(&reentryGuardA, true);
// do some stuff that might cause reentry of this function
// this section is both early-exit and exception proof, with regards to restoring
// the guard variable to its original state
}
}
I'm looking for a graceful way to do this in C# using the disposal pattern (or maybe some other mechanism?) I'm thinking that passing a delegate to call might work, but seems a bit more error-prone than the guard above. Suggestions welcome!
Something like:
void someFunction() {
if(!reentryGuard) {
using(var guard = new BoolGuard(ref reentryGuard, true)) {
// do some stuff that might cause reentry of this function
// this section is both early-exit and exception proof, with regards to restoring
// the guard variable to its original state
}
}
}
With the understanding that the above code won't work.
You are correct…without unsafe code, you can't save the address of a by-ref parameter. But, depending on how much you can change the overall design, you can create a "guardable" type, such that it's a reference type containing the value to actually guard.
For example:
class Program
{
class Guardable<T>
{
public T Value { get; private set; }
private sealed class GuardHolder<TGuardable> : IDisposable where TGuardable : Guardable<T>
{
private readonly TGuardable _guardable;
private readonly T _originalValue;
public GuardHolder(TGuardable guardable)
{
_guardable = guardable;
_originalValue = guardable.Value;
}
public void Dispose()
{
_guardable.Value = _originalValue;
}
}
public Guardable(T value)
{
Value = value;
}
public IDisposable Guard(T newValue)
{
GuardHolder<Guardable<T>> guard = new GuardHolder<Guardable<T>>(this);
Value = newValue;
return guard;
}
}
static void Main(string[] args)
{
Guardable<int> guardable = new Guardable<int>(5);
using (var guard = guardable.Guard(10))
{
Console.WriteLine(guardable.Value);
}
Console.WriteLine(guardable.Value);
}
}
Here's a functional (as in lambda-based) way to do it. Pluses are, no need to use a using:
(note: This is not thread-safe. If you are looking to keep different threads from running the same code simultaneously, look at the lock statement, the monitor, and the mutex)
// usage
GuardedOperation TheGuard = new GuardedOperation() // instance variable
public void SomeOperationToGuard()
{
this.TheGuard.Execute(() => TheCodeToExecuteGuarded);
}
// implementation
public class GuardedOperation
{
public bool Signalled { get; private set; }
public bool Execute(Action guardedAction)
{
if (this.Signalled)
return false;
this.Signalled = true;
try
{
guardedAction();
}
finally
{
this.Signalled = false;
}
return true;
}
}
EDIT
Here is how you could use the guarded with parameters:
public void SomeOperationToGuard(int aParam, SomeType anotherParam)
{
// you can pass the params to the work method using closure
this.TheGuard.Execute(() => TheMethodThatDoesTheWork(aParam, anotherParam);
}
private void TheMethodThatDoesTheWork(int aParam, SomeType anotherParam) {}
You could also introduce overloads of the Execute method that accept a few different variants of the Action delegate, like Action<T> and Action<T1, T2>
If you need return values, you could introduce overloads of Execute that accept Func<T>
Sounds like the sort of thing you'd have to implement yourself - there are no such mechanisms built into C# or the .NET framework, though I did locate a deprecated class Guard on MSDN.
This sort of functionality would likely need to use a Using statement to operate without passing around an Action block, which as you said could get messy. Note that you can only call using against and IDisposable object, which will then be disposed - the perfect trigger for resetting the value of the object in question.
You can derive your object from IDisposable interface and implement it.
In specific case you are presenting here Dispose will be called as soon as you leave using scope.
Example:
public class BoolGuard : IDisposable
{
....
...
public void Dispose()
{
//DISPOSE IMPLEMANTATION
}
}

how to prevent a deadlock when you need to lock multiple objects

Image this code:
You have 2 arrays, and you need to lock both of them in same moment (for any reason - you just need to keep locked both of them because they are somehow depending on each other) - you could nest the lock
lock (array1)
{
lock (array2)
{
... do your code
}
}
but this may result in a deadlock in case that someone in other part of your code would do
lock (array2)
{
lock (array1)
{
... do your code
}
}
and array 1 was locked - execution context switched - then array 2 was locked by second thread.
Is there a way to atomically lock them? such as
lock_array(array1, array2)
{
....
}
I know I could just create some extra "lock object" and lock that instead of both arrays everywhere in my code, but that just doesn't seem correct to me...
In general you should avoid locking on publicly accessible members (the arrays in your case). You'd rather have a private static object you'd lock on.
You should never allow locking on publicly accessible variable as Darin said. For example
public class Foo
{
public object Locker = new object();
}
public class Bar
{
public void DoStuff()
{
var foo = new Foo();
lock(foo.Locker)
{
// doing something here
}
}
}
rather do something like this.
public class Foo
{
private List<int> toBeProtected = new List<int>();
private object locker = new object();
public void Add(int value)
{
lock(locker)
{
toBeProtected.Add(value);
}
}
}
The reason for this is if you have multiple threads accessing multiple public synchronization constructs then run the very real possiblity of deadlock. Then you have to be very careful about how you code. If you are making your library available to others can you be sure that you can grab the lock? Perhaps someone using your library has also grabbed the lock and between the two of you have worked your way into a deadlock scenario. This is the reason Microsoft recommend not using SyncRoot.
I am not sure what you mean by lock to arrays.
You can easily perform operation on both arrays in single lock.
static readonly object a = new object();
lock(a){
//Perform operation on both arrays
}

C# MultiThread Safe Class Design

I'm trying to designing a class and I'm having issues with accessing some of the nested fields and I have some concerns with how multithread safe the whole design is. I would like to know if anyone has a better idea of how this should be designed or if any changes that should be made?
using System;
using System.Collections;
namespace SystemClass
{
public class Program
{
static void Main(string[] args)
{
System system = new System();
//Seems like an awkward way to access all the members
dynamic deviceInstance = (((DeviceType)((DeviceGroup)system.deviceGroups[0]).deviceTypes[0]).deviceInstances[0]);
Boolean checkLocked = deviceInstance.locked;
//Seems like this method for accessing fields might have problems with multithreading
foreach (DeviceGroup dg in system.deviceGroups)
{
foreach (DeviceType dt in dg.deviceTypes)
{
foreach (dynamic di in dt.deviceInstances)
{
checkLocked = di.locked;
}
}
}
}
}
public class System
{
public ArrayList deviceGroups = new ArrayList();
public System()
{
//API called to get names of all the DeviceGroups
deviceGroups.Add(new DeviceGroup("Motherboard"));
}
}
public class DeviceGroup
{
public ArrayList deviceTypes = new ArrayList();
public DeviceGroup() {}
public DeviceGroup(string deviceGroupName)
{
//API called to get names of all the Devicetypes
deviceTypes.Add(new DeviceType("Keyboard"));
deviceTypes.Add(new DeviceType("Mouse"));
}
}
public class DeviceType
{
public ArrayList deviceInstances = new ArrayList();
public bool deviceConnected;
public DeviceType() {}
public DeviceType(string DeviceType)
{
//API called to get hardwareIDs of all the device instances
deviceInstances.Add(new Mouse("0001"));
deviceInstances.Add(new Keyboard("0003"));
deviceInstances.Add(new Keyboard("0004"));
//Start thread CheckConnection that updates deviceConnected periodically
}
public void CheckConnection()
{
//API call to check connection and returns true
this.deviceConnected = true;
}
}
public class Keyboard
{
public string hardwareAddress;
public bool keypress;
public bool deviceConnected;
public Keyboard() {}
public Keyboard(string hardwareAddress)
{
this.hardwareAddress = hardwareAddress;
//Start thread to update deviceConnected periodically
}
public void CheckKeyPress()
{
//if API returns true
this.keypress = true;
}
}
public class Mouse
{
public string hardwareAddress;
public bool click;
public Mouse() {}
public Mouse(string hardwareAddress)
{
this.hardwareAddress = hardwareAddress;
}
public void CheckClick()
{
//if API returns true
this.click = true;
}
}
}
Making a class thread-safe is a heck of a difficult thing to do.
The first, naive, way, that many tends to attempt is just adding a lock and ensuring that no code that touches mutable data does so without using the lock. By that I mean that everything in the class that is subject to change, has to first lock the locking object before touching the data, be it just reading from it, or writing to it.
However, if this is your solution, then you should probably not do anything at all to the code, just document that the class is not thread-safe and leave it to the programmer that uses it.
Why?
Because you've effectively just serialized all access to it. Two threads that tries use the class at the same time, even though they are touching separate parts of it, will block. One of the threads will be given access, the other one will wait until the first one is complete.
This is actually discouraging multi-threaded usage of your class, so in this case you're adding overhead of locking to your class, and not actually getting any benefits from it. Yes, your class is now "thread safe", but it isn't actually a good thread-citizen.
The other way is to start adding granular locks, or writing lock-free constructs (seriously hard), so that if two parts of the object aren't always related, code that accesses each part have their own lock. This would allow multiple threads that accesses different parts of the data to run in parallel without blocking one another.
This becomes hard wherever you need to work on more than one part of the data at a time, as you need to be super-careful to take the locks in the right order, or suffer deadlocks. It should be your class' responsibility to ensure the locks are taken in the right order, not the code that uses the class.
As for your specific example, it looks to me as though the parts that will change from background threads are only the "is the device connected" boolean values. In this case I would make that field volatile, and use a lock around each. If, however, the list of devices will change from background threads, you're going to run into problems pretty fast.
You should first try to identify all the parts that will be changed by background threads, and then devise scenarios for how you want the changes to propagate to other threads, how to react to the changes, etc.

'using' statement vs 'try finally'

I've got a bunch of properties which I am going to use read/write locks on. I can implement them either with a try finally or a using clause.
In the try finally I would acquire the lock before the try, and release in the finally. In the using clause, I would create a class which acquires the lock in its constructor, and releases in its Dispose method.
I'm using read/write locks in a lot of places, so I've been looking for ways that might be more concise than try finally. I'm interested in hearing some ideas on why one way may not be recommended, or why one might be better than another.
Method 1 (try finally):
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
get
{
rwlMyLock_m .AcquireReaderLock(0);
try
{
return dtMyDateTime_m
}
finally
{
rwlMyLock_m .ReleaseReaderLock();
}
}
set
{
rwlMyLock_m .AcquireWriterLock(0);
try
{
dtMyDateTime_m = value;
}
finally
{
rwlMyLock_m .ReleaseWriterLock();
}
}
}
Method 2:
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m
public DateTime MyDateTime
{
get
{
using (new ReadLock(rwlMyLock_m))
{
return dtMyDateTime_m;
}
}
set
{
using (new WriteLock(rwlMyLock_m))
{
dtMyDateTime_m = value;
}
}
}
public class ReadLock : IDisposable
{
private ReaderWriterLock rwl;
public ReadLock(ReaderWriterLock rwl)
{
this.rwl = rwl;
rwl.AcquireReaderLock(0);
}
public void Dispose()
{
rwl.ReleaseReaderLock();
}
}
public class WriteLock : IDisposable
{
private ReaderWriterLock rwl;
public WriteLock(ReaderWriterLock rwl)
{
this.rwl = rwl;
rwl.AcquireWriterLock(0);
}
public void Dispose()
{
rwl.ReleaseWriterLock();
}
}
From MSDN, using Statement (C# Reference)
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler. The code example earlier expands to the following code at compile time (note the extra curly braces to create the limited scope for the object):
{
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
}
So basically, it is the same code but with a nice automatic null-checks and an extra scope for your variable. The documentation also states that it "ensures the correct use of IDisposable object" so you might as well gets even better framework support for any obscure cases in the future.
So go with option 2.
Having the variable inside a scope that ends immediately after it's no longer needed is also a plus.
I definitely prefer the second method. It is more concise at the point of usage, and less error prone.
In the first case someone editing the code has to be careful not to insert anything between the Acquire(Read|Write)Lock call and the try.
(Using a read/write lock on individual properties like this is usually overkill though. They are best applied at a much higher level. A simple lock will often suffice here since the possibility of contention is presumably very small given the time the lock is held for, and acquiring a read/write lock is a more expensive operation than a simple lock).
Consider the possibility that both solutions are bad because they mask exceptions.
A try without a catch should obviously be a bad idea; see MSDN for why the using statement is likewise dangerous.
Note also Microsoft now recommends ReaderWriterLockSlim instead of ReaderWriterLock.
Finally, note that the Microsoft examples use two try-catch blocks to avoid these issues, e.g.
try
{
try
{
//Reader-writer lock stuff
}
finally
{
//Release lock
}
}
catch(Exception ex)
{
//Do something with exception
}
A simple, consistent, clean solution is a good goal, but assuming you can't just use lock(this){return mydateetc;}, you might reconsider the approach; with more info I'm sure Stack Overflow can help ;-)
I personally use the C# "using" statement as often as possible, but there are a few specific things that I do along with it to avoid the potential issues mentioned. To illustrate:
void doSomething()
{
using (CustomResource aResource = new CustomResource())
{
using (CustomThingy aThingy = new CustomThingy(aResource))
{
doSomething(aThingy);
}
}
}
void doSomething(CustomThingy theThingy)
{
try
{
// play with theThingy, which might result in exceptions
}
catch (SomeException aException)
{
// resolve aException somehow
}
}
Note that I separate the "using" statement into one method and the use of the object(s) into another method with a "try"/"catch" block. I may nest several "using" statements like this for related objects (I sometimes go three or four deep in my production code).
In my Dispose() methods for these custom IDisposable classes, I catch exceptions (but NOT errors) and log them (using Log4net). I have never encountered a situation where any of those exceptions could possibly affect my processing. The potential errors, as usual, are allowed to propagate up the call stack and typically terminate processing with an appropriate message (the error and stack trace) logged.
If I somehow encountered a situation where a significant exception could occur during Dispose(), I would redesign for that situation. Frankly, I doubt that will ever happen.
Meanwhile, the scope and cleanup advantages of "using" make it one of my most favorite C# features. By the way, I work in Java, C#, and Python as my primary languages, with lots of others thrown in here and there, and "using" is one of my most favorite language features all around because it is a practical, everyday workhorse.
I like the 3rd option
private object _myDateTimeLock = new object();
private DateTime _myDateTime;
public DateTime MyDateTime{
get{
lock(_myDateTimeLock){return _myDateTime;}
}
set{
lock(_myDateTimeLock){_myDateTime = value;}
}
}
Of your two options, the second option is the cleanest and easier to understand what's going on.
"Bunch of properties" and locking at the property getter and setter level looks wrong. Your locking is much too fine-grained. In most typical object usage, you'd want to make sure that you acquired a lock to access more than one property at the same time. Your specific case might be different but I kinda doubt it.
Anyway, acquiring the lock when you access the object instead of the property will significantly cut down on the amount of locking code you'll have to write.
DRY says: second solution. The first solution duplicates the logic of using a lock, whereas the second does not.
Try/Catch blocks are generally for exception handling, while using blocks are used to ensure that the object is disposed.
For the read/write lock a try/catch might be the most useful, but you could also use both, like so:
using (obj)
{
try { }
catch { }
}
so that you can implicitly call your IDisposable interface as well as make exception handling concise.
The following creates extension methods for the ReaderWriterLockSlim class that allow you to do the following:
var rwlock = new ReaderWriterLockSlim();
using (var l = rwlock.ReadLock())
{
// read data
}
using (var l = rwlock.WriteLock())
{
// write data
}
Here's the code:
static class ReaderWriterLockExtensions() {
/// <summary>
/// Allows you to enter and exit a read lock with a using statement
/// </summary>
/// <param name="readerWriterLockSlim">The lock</param>
/// <returns>A new object that will ExitReadLock on dispose</returns>
public static OnDispose ReadLock(this ReaderWriterLockSlim readerWriterLockSlim)
{
// Enter the read lock
readerWriterLockSlim.EnterReadLock();
// Setup the ExitReadLock to be called at the end of the using block
return new OnDispose(() => readerWriterLockSlim.ExitReadLock());
}
/// <summary>
/// Allows you to enter and exit a write lock with a using statement
/// </summary>
/// <param name="readerWriterLockSlim">The lock</param>
/// <returns>A new object that will ExitWriteLock on dispose</returns>
public static OnDispose WriteLock(this ReaderWriterLockSlim rwlock)
{
// Enter the write lock
rwlock.EnterWriteLock();
// Setup the ExitWriteLock to be called at the end of the using block
return new OnDispose(() => rwlock.ExitWriteLock());
}
}
/// <summary>
/// Calls the finished action on dispose. For use with a using statement.
/// </summary>
public class OnDispose : IDisposable
{
Action _finished;
public OnDispose(Action finished)
{
_finished = finished;
}
public void Dispose()
{
_finished();
}
}
I think method 2 would be better.
Simpler and more readable code in your properties.
Less error-prone since the locking code doesn't have to be re-written several times.
While I agree with many of the above comments, including the granularity of the lock and questionable exception handling, the question is one of approach. Let me give you one big reason why I prefer using over the try {} finally model... abstraction.
I have a model very similar to yours with one exception. I defined a base interface ILock and in it I provided one method called Acquire(). The Acquire() method returned the IDisposable object and as a result means that as long as the object I am dealing with is of type ILock that it can be used to do a locking scope. Why is this important?
We deal with many different locking mechanisms and behaviors. Your lock object may have a specific timeout that employs. Your lock implementation may be a monitor lock, reader lock, writer lock or spin lock. However, from the perspective of the caller all of that is irrelevant, what they care about is that the contract to lock the resource is honored and that the lock does it in a manner consistent with it's implementation.
interface ILock {
IDisposable Acquire();
}
class MonitorLock : ILock {
IDisposable Acquire() { ... acquire the lock for real ... }
}
I like your model, but I'd consider hiding the lock mechanics from the caller. FWIW, I've measured the overhead of the using technique versus the try-finally and the overhead of allocating the disposable object will have between a 2-3% performance overhead.
I'm surprised no one has suggested encapsulating the try-finally in anonymous functions. Just like the technique of instantiating and disposing of classes with the using statement, this keeps the locking in one place. I prefer this myself only because I'd rather read the word "finally" than the word "Dispose" when I'm thinking about releasing a lock.
class StackOTest
{
private delegate DateTime ReadLockMethod();
private delegate void WriteLockMethod();
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m;
public DateTime MyDateTime
{
get
{
return ReadLockedMethod(
rwlMyLock_m,
delegate () { return dtMyDateTime_m; }
);
}
set
{
WriteLockedMethod(
rwlMyLock_m,
delegate () { dtMyDateTime_m = value; }
);
}
}
private static DateTime ReadLockedMethod(
ReaderWriterLock rwl,
ReadLockMethod method
)
{
rwl.AcquireReaderLock(0);
try
{
return method();
}
finally
{
rwl.ReleaseReaderLock();
}
}
private static void WriteLockedMethod(
ReaderWriterLock rwl,
WriteLockMethod method
)
{
rwl.AcquireWriterLock(0);
try
{
method();
}
finally
{
rwl.ReleaseWriterLock();
}
}
}
SoftwareJedi, I don't have an account, so I can't edit my answers.
In any case, the previous version wasn't really good for general purpose use since the read lock always required a return value. This fixes that:
class StackOTest
{
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m;
public DateTime MyDateTime
{
get
{
DateTime retval = default(DateTime);
ReadLockedMethod(
delegate () { retval = dtMyDateTime_m; }
);
return retval;
}
set
{
WriteLockedMethod(
delegate () { dtMyDateTime_m = value; }
);
}
}
private void ReadLockedMethod(Action method)
{
rwlMyLock_m.AcquireReaderLock(0);
try
{
method();
}
finally
{
rwlMyLock_m.ReleaseReaderLock();
}
}
private void WriteLockedMethod(Action method)
{
rwlMyLock_m.AcquireWriterLock(0);
try
{
method();
}
finally
{
rwlMyLock_m.ReleaseWriterLock();
}
}
}
Actually in your first example, to make the solutions comparable, you would also implement IDisposable there as well. Then you'd call Dispose() from the finally block instead of releasing the lock directly.
Then you'd be "apples to apples" implementation (and MSIL)-wise (MSIL will be the same for both solutions). It's still probably a good idea to use using because of the added scoping and because the Framework will ensure proper usage of IDisposable (the latter being less beneficial if you're implementing IDisposable yourself).
Silly me. There's a way to make that even simpler by making the locked methods part of each instance (instead of static like in my previous post). Now I really prefer this because there's no need to pass `rwlMyLock_m' off to some other class or method.
class StackOTest
{
private delegate DateTime ReadLockMethod();
private delegate void WriteLockMethod();
static ReaderWriterLock rwlMyLock_m = new ReaderWriterLock();
private DateTime dtMyDateTime_m;
public DateTime MyDateTime
{
get
{
return ReadLockedMethod(
delegate () { return dtMyDateTime_m; }
);
}
set
{
WriteLockedMethod(
delegate () { dtMyDateTime_m = value; }
);
}
}
private DateTime ReadLockedMethod(ReadLockMethod method)
{
rwlMyLock_m.AcquireReaderLock(0);
try
{
return method();
}
finally
{
rwlMyLock_m.ReleaseReaderLock();
}
}
private void WriteLockedMethod(WriteLockMethod method)
{
rwlMyLock_m.AcquireWriterLock(0);
try
{
method();
}
finally
{
rwlMyLock_m.ReleaseWriterLock();
}
}
}

Categories

Resources