C# 在未涉及的类中检测调用是否包装在使用另一个
首先,很抱歉问了这么难的题目,但我想不出比这更好的了。 如果有人知道更好的描述,我很乐意更改标题!:) 假设我有以下两个类的代码:C# 在未涉及的类中检测调用是否包装在使用另一个,c#,design-patterns,singleton,using,C#,Design Patterns,Singleton,Using,首先,很抱歉问了这么难的题目,但我想不出比这更好的了。 如果有人知道更好的描述,我很乐意更改标题!:) 假设我有以下两个类的代码: using(new Wrapper()) { Inner.Do(); } public class Wrapper : IDisposable { public static Wrapper Instance { get; set; } public Wrapper() { Instance = this;
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语句中
不幸的是,静态实例变量是我能想到的实现上述目标的最佳方式,但它肯定不是最佳情况。
假设两个线程同时执行上述代码。一个线程将覆盖另一个线程的实例,导致未接受的beaviour和race条件
问题:
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 */ }
}
}
有没有人能告诉我一个解决方案,在这个解决方案中,我仍然能够完成上述任务,但不使用静态实例变量
提前谢谢
回答
由于这只是对一些新内容的测试,所以我现在使用ThreadStaticAttribute。
但正如Marc Gravell所说,如果正在进行异步操作,则不要使用此选项
用法见克里斯·范德莫顿的答案。我个人的建议很简单:不需要这样做。你是对的,没有神奇的方法可以做到这一点。线程问题可以通过
[ThreadStatic]
处理,但如果涉及多个线程,例如async
,则无法很好地解决。如果可能,我会说:找到一种不同的实现策略,它不需要使用块检测不相关的。同样,您的代码将很难检测到使用
和简单地:
new Wrapper(); // note this doesn't dispose cleanly
Inner.Do();
一些静态实例的另一个问题是,您还需要考虑多个嵌套块;将需要一个
堆栈
,或者您可以缓存上一个值以将其设置回一次性对象中。您需要使用ThreadStatic属性标记支持实例属性的字段,如下所示:
[ThreadStatic]
private static Wrapper instance;
public static Wrapper Instance
{
get { return instance; }
}
另见
您可能还需要处理重入(即嵌套使用)。这是一个很好的答案!我将把它标记为正确,并在我的原始问题中写一些东西。一定要看!我将编辑我的问题。你能解释一下为什么多线程不能很好地工作,因为(据我所知)这个属性的用例是多线程的吗?