1

まず、難しい質問のタイトルで申し訳ありませんが、これ以上良いものは思いつきません。誰かがより良い説明を知っていれば、タイトルを変更したいと思います! :)

2 つのクラスを含む次のコードがあるとします。

using(new Wrapper())
{
    Inner.Do();
}

public class Wrapper : IDisposable
{
    public static Wrapper Instance { get; set; }
    public Wrapper()
    {
        Instance = this;
    }

    public void Dispose()
    {
        Instance = null;
    }
}
public static class Inner
{
    public static Do()
    {
        if (Wrapper.Instance == null)
        { /* no using */ }
        else
        { /* with using */ }
    }
}

上記のコードは意図したとおりに機能し、コードが using ステートメントでラップされているかどうかを検出できます。

残念ながら、静的なインスタンス変数は、上記を達成するために私が考えることができる最良の方法ですが、それは確かに最良のケースではありません. 2 つのスレッドが上記のコードを「同時に」実行するとします。1 つのスレッドが別のスレッドのインスタンスを上書きし、例外のない動作と競合状態につながります。

質問:

静的インスタンス変数を使用せずに、上記を実行できるソリューションを誰かに教えてもらえますか?

前もって感謝します!

答え

これは単なる新しいテストであるため、現在 ThreadStaticAttribute を使用しています。しかし、Marc Gravell が述べたように、非同期操作が行われている場合はこれを使用しないでください。

使用法については、Kris Vandermotten の回答を参照してください。

4

2 に答える 2

2

個人的に私は簡単にアドバイスします:それをする必要はありません。あなたはそれをする魔法の方法がないという点で正しいです。スレッドの問題はを介して処理できますが[ThreadStatic]、たとえば、複数のスレッドが関係している場合はうまく機能しませんasync。可能であれば、私は言うでしょう:無関係なusingブロックを検出する必要のない別の実装戦略を見つけてください。同様に、コードはとの違いを検出するのに苦労しますusing

new Wrapper(); // note this doesn't dispose cleanly
Inner.Do();

一部の静的インスタンスに関する別の問題は、複数のネストされたブロックも考慮する必要があることです。が必要Stack<Wrapper>になるか、以前の値をキャッシュして使い捨てオブジェクトに戻すことができます。

于 2012-07-24T06:51:27.810 に答える
0

You need to mark the field backing the Instance property with a ThreadStatic attribute, like this:

[ThreadStatic]
private static Wrapper instance;

public static Wrapper Instance
{
    get { return instance; }
}

See also http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx

You may also have to deal with reentrance (i.e. nested usings).

于 2012-07-24T06:59:37.830 に答える