私は車輪を再発明しているように感じます.誰かがすでにコードに頭をぶつけて、この問題を解決する優れた安定したテスト済みのパターンを思いついた可能性が十分にあります.まだ遭遇していません。
私は今私のために働くと思われる次の解決策を思いつきました。
スレッドセーフな方法でアクセスする必要があるオブジェクトを操作するための一貫したインターフェイスを提供することになっています。
@pstはこれを「アトミック」オブジェクト get/set holderと呼んでいますが、これは他の場所で使用されているパターンですか?
インターフェースは次のとおりです。
public interface ISynched<T>
{
bool Read( ref T value );
bool Read( ref T value, TimeSpan timeout );
bool Write( T value );
bool Write( T value, TimeSpan timeout );
bool Do( Action<T> roAction );
bool Do( Action<T> roAction, TimeSpan timeout );
bool Do( Action<T, Action<T>> rwAction );
bool Do( Action<T, Action<T>> rwAction, TimeSpan timeout );
}
実装は次のとおりです。
public class Synched<T>: ISynched<T>
{
static public readonly TimeSpan Infinity = TimeSpan.FromMilliseconds(-1);
private T _value;
public static Synched<T> MakeSynched( T value )
{
return new Synched<T>() { _value = value };
}
private Synched() {}
public bool Read( ref T value )
{
return Read( ref value, Infinity );
}
public bool Read( ref T value, TimeSpan timeout )
{
var tmp = default(T);
var success = Do( (v) => tmp = v, timeout );
if( success ) value = tmp;
return success;
}
public bool Write( T value )
{
return Do( (v, set) => set(v) );
}
public bool Write( T value, TimeSpan timeout )
{
return Do( (v, set) => set(v), timeout );
}
public bool Do( Action<T> roAction )
{
return Do( roAction, Infinity );
}
public bool Do( Action<T> roAction, TimeSpan timeout )
{
bool lockWasTaken = false;
try
{
Monitor.TryEnter(this, timeout, ref lockWasTaken);
if(!lockWasTaken) return false;
roAction( _value );
return true;
}
finally
{
if (lockWasTaken) Monitor.Exit(this);
}
}
public bool Do( Action<T, Action<T>> rwAction )
{
return Do( rwAction, Infinity);
}
public bool Do( Action<T, Action<T>> rwAction, TimeSpan timeout )
{
bool lockWasTaken = false;
try
{
Monitor.TryEnter(this, timeout, ref lockWasTaken);
if(!lockWasTaken) return false;
rwAction( _value, value => _value = value );
return true;
}
finally
{
if (lockWasTaken) Monitor.Exit(this);
}
}
}
Synched オブジェクトの作成をコーディングしやすくするための静的で非ジェネリックなクラスを追加します。
public static class Synched
{
public static Synched<T> MakeSynched<T>( T value )
{
return Synched<T>.MakeSynched( value );
}
}
編集: より意味のあるように例を変更しました サンプルの使用例は次のようになります (コードは何の意味もありません。単なる例です (悪い例です):
var synchedCol = Synched.MakeSynched( new List<SomeClass>() );
synchedCol.Do( c => {
c.Add(new SomeClass());
c.Add(new SomeClass() { Property1 = "something" } );
} );
var i = 1;
SomeClass val;
synchedCol.Do( c => val = c[i] );
var i = 1;
synchedCol.Do( c => {
if( c[i].Property1 == "something" )
{
c.Remove(c[i]);
}
});
それで、私は正しい軌道に乗っていますか?誰かが似たようなことに遭遇しましたか?類似した既存のパターンはありますか?