1

首先,对于这个困难的问题标题感到抱歉,但我想不出更好的了。如果有人知道更好的描述,我很乐意更改标题!:)

假设我有以下两个类的代码:

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 语句中。

不幸的是,静态实例变量是我能想到的实现上述目标的最佳方式,但它肯定不是最好的情况。假设两个线程在“同一”时间执行上述代码。一个线程会覆盖另一个线程的实例,从而导致异常行为和竞争条件。

问题:

任何人都可以指导我找到我仍然能够执行上述操作但不使用静态实例变量的解决方案吗?

提前致谢!

回答

由于这只是对新事物的测试,因此我现在使用 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

您需要使用 ThreadStatic 属性标记支持 Instance 属性的字段,如下所示:

[ThreadStatic]
private static Wrapper instance;

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

另请参阅http://msdn.microsoft.com/en-us/library/system.threadstaticattribute.aspx

您可能还必须处理重入(即嵌套使用)。

于 2012-07-24T06:59:37.830 回答