2016-08-23 2 views
0

スコープ内にラップされたいくつかの操作で同じでなければならないいくつかの種類の共有ディスポーザブルリソース(スコープまたはコンテキスト)を実装したいと思います。 EXの場合:(私たちはのTransactionScopeを使用しているように、それを直接渡さず)C#でコンテキスト/スコープ内で操作をラップする最善の方法

using(var ctx = Context.Create()) 
{ 
    var obj = ReadSmth(); 
    ChangeObject(obj); 
    SomeActionWithReadWriteInside(); 
    Write(obj); 
} 

読む、変更、書き込みは内部コンテキストオブジェクトのまったく同じインスタンスを使用する必要があります。また、ChangeObjectメソッド内で他の読み取り/書き込み操作が発生した場合にも、このコンテキストに含める必要があります。しかし、別のスレッドで(ctx)ブロックを使用しているもう1つのスレッドは、そのコンテキストに干渉してはいけません。

UPD1:スーパーグローバルオブジェクトの導入、ASP.NETスレッドの切り替えに関する問題、async/part-switchingとtestingの問題を待っている問題を理解しています。しかし、場合によっては、このアプローチには一定の制限があり、ソリューション内に存在する権利があります。私はちょうどこのパターンの構造を尋ねたい。

.NET/C#でこのような種類の動作を実装する最良の方法は何ですか?

UPD2:そこに独自の問題にはいくつかの既存のソリューションとなっているので、それが業界標準として使用することができないように思えるが、で開始するには良い方法:

+1

スレッドローカルストレージを使用しますか? –

+0

私は、メソッドの中のすべてのメソッドやメソッドの中でコンテキストを渡さずにコードをよりきれいにしたいと思っています。内部にたくさんのネストメソッドが存在する可能性があります。 –

+0

Daniel A. White:そうかもしれませんが、マルチスレッド環境のすべての状況で最適なソリューションですか? –

答えて

2

これはC#がネイティブにサポートされているわけではありません。あなたがそれをしたい場合は、独自のソリューションをロールバックする必要があります。ここではアプローチがありますが、私はそれを実稼働環境で使用したくはありません。変数を渡すことはそれほど複雑ではないので、複雑さは価値があります。また、コードは、あなたがしなければならないことは、大きな臭いグローバル(あなたの「現在のコンテキスト」)を導入し、テストして分離するのがはるかに難しいコードを書いたという点で「クリーン」ではありません。

しかし、それは...そう、ここで、考えるように面白いアプローチだ

まず、すべてのコンテキストのスタックを含むThreadStatic変数を作成します。

次に、新しいコンテキストを作成してスタックに追加し、破棄してスタックからポップします。

その後
public class Context: IDisposable 
{ 
    public Context 
    { 
     Contexts.ContextCreated(this); 
    } 

    public void Dispose 
    { 
     Contexts.ContextDisposed(this); 
    } 
} 

それを使用する、あなただけの

Contexts.CurrentContext 

を参照してください。これは、しかし、エラーに満ちています。たとえば、マルチスレッドコード、またはasync/awaitを使用するコードでは、これはひどく失敗します。私たちがやっていることは、コールスタックと同等のものを維持することです。コールスタックに何かを得るための簡単で十分なサポート方法があります。それがメソッドパラメータです。

+0

、スティーブありがとう!それはまずは​​良いアプローチです。私はThreadStaticを使用してそのすべてのライフサイクルを制御し、コンテキストを格納するための何らかのディクショナリを使用することはできないと考えています。 –

+0

スレッド静的/スタックパターンは、関数呼び出しで何が起こるかを反映します。辞書があなたに与えるものを知ることに興味がありますか? –

+0

ThreadStaticはASP.NET環境とThreadPoolにも意味を持たないので、私は異なるプラットフォームに対して異なるテクニックを作りたいと思っています。私は辞書とスタックの両方がオーバーヘッドだと思ったので、内部スコープを格納するためにリンクを持つオブジェクトを作成することができます。また、私はいくつかの改善(辞書を取り除き、ThreadStaticの代わりにASP.NET implementaionのHttpContext.Current.Itemsを使用する)に適した実装を見つけたようです - https://github.com/minimod/minimods/blob/ master/MiniMods/ThreadVariable/ThreadVariable.cs –

関連する問題