I borrowed this class from the Wes Dyer's LINQ to ASCII Art post. It's a great way to return IDisposable from a method without creating a specialized class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace System {
public class ActionDisposable: IDisposable {
Action action;
public ActionDisposable(Action action) {
this.action = action;
}
public void Dispose() {
action();
}
}
}
Wes uses ActionDisposable casually to reset Console properties. My example to demonstrate this class will be similar to Eilon Lipton's solution to locking a collection, expect I'll use ActionDisposable instead of specialized ReadLockDisposable and WriteLockDisposable.
public class SingletonSafeCollection<T>: Collection<T>
{
private static readonly SingletonSafeCollection<T> instance = new SingletonSafeCollection<T>();
public static SingletonSafeCollection<T> Instance {
get
{
return instance;
}
}
private ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
/// <summary>Acquires a read lock for reading the collection</summary>
/// <returns>Disposable object that releases the read lock</returns>
public IDisposable GetReadLock()
{
rwLock.EnterReadLock();
return new ActionDisposable(rwLock.ExitReadLock);
}
/// <summary>Acquires a write lock for writing the collection</summary>
/// <returns>Disposable object that releases the write lock</returns>
public IDisposable GetWriteLock()
{
rwLock.EnterWriteLock();
return new ActionDisposable(rwLock.ExitWriteLock);
}
}
Now I can use the SingletonSafeCollection<T> anywhere in my code with guarantees that when I one takes a read lock, no one will be writing to the collection and when one takes a write lock, no one will be writing to the collection.
static void Main(string[] args)
{
SingletonSafeCollection<int> numbers = SingletonSafeCollection<int>.Instance;
using (numbers.GetWriteLock())
{
// safe to write with a guarentee no one is reading or modifying the collection (except this thread)
numbers.Add(1212);
}
using (numbers.GetReadLock())
{
// safe to read the list with a guarentee no one is modifying the collection
numbers.ToList().ForEach(i => Console.WriteLine(i));
}
Console.ReadLine();
}