Я написал это очень быстро и не проверял, и я публикую его только для того, чтобы передать общую идею об одном подходе к условной блокировке с использованием методов расширения и делегатов или лямбда-функций.Без тестирования я также не могу сказать, будет ли это саморазрушением, что, безусловно, возможно.
У меня есть код, который выполняется как в многопоточных процессах, так и в процессах, использующих модель потоков с кооперативным волоконным режимом.(например, там, где есть несколько потоков, которые никогда не выполняются асинхронно).В приложении с кооперативным оптоволоконным режимом блокировка бессмысленна и расточительна, поэтому это может быть решением, позволяющим избежать большого количества грязной логики в каждой точке, где необходимо выполнить блокировку.
// Conditional Locking concept code
namespace SystemExtensions {
public static class LockMeUp
{
private static bool isLockingEnabled = true;
// If set to true, locking will be performed
// by the extension methods below.
internal static bool LockingEnabled
{
get
{
return isLockingEnabled;
}
set
{
isLockingEnbaled = value;
}
}
static void CheckNull<TLock>( TLock target ) where TLock: class
{
if( target == null )
throw new ArgumentNullException("target cannot be null");
}
// Invoke the supplied action on the supplied lock object
public static void TryLock<TLock>(
this TLock target,
Action<TLock> action ) where TLock: class
{
CheckNull( target );
if( isLockingEnabled )
{
lock( target )
{
action( target );
}
}
else
{
action( target );
}
}
// Invoke the supplied function on the supplied
// lock object and return result:
public static T TryLock<TLock, T>(
this TLock target,
Func<TLock, T> func ) where TLock: class
{
CheckNull( target );
if( isLockingEnabled )
{
lock( target )
{
return func( target );
}
}
else
{
return func( target );
}
}
// Invoke the supplied function on the supplied lock object
// and another supplied argument, and return the result:
public static T TryLock<TLock, TArg, T>(
this TLock target,
Func<TLock, TArg, T> func,
TArg arg ) where TLock: class
{
CheckNull( target );
if( isLockingEnabled )
{
lock( target )
{
return func( target, arg );
}
}
else
{
return func( target, arg );
}
}
// Invoke the supplied action on the supplied lock object
// and another supplied argument:
public static void TryLock<TLock, TArg>(
this TLock target,
Action<TLock, TArg> func,
TArg arg ) where TLock: class
{
CheckNull( target );
if( isLockingEnabled )
{
lock( target )
{
func( target, arg );
}
}
else
{
func( target, arg );
}
}
}
///// Example:
public static class SharedList<T>
{
private static List<T> items = new List<T>();
public static bool Remove( T item )
{
return items.TryLock( (list, item) => list.Remove( item ), item );
}
public static T GetItemAt( int index )
{
return items.TryLock( (list, i) => list[i], index );
}
public static bool Contains( T item )
{
return items.TryLock( (list, it) => list.Contains( it ), item );
}
public static void Add( T item )
{
items.TryLock( (list, item) => list.Add( item ) );
}
}
} // namespace