我在asp.net mvc应用程序中使用了以下静态类(为了清晰起见而简化)
public static class GObjContextHelper
{
private static readonly object _lock = new object();
public static GObjContext GetObjContext()
{
Trace.TraceInformation("_lock: " + _lock);
//lock (_lock)
//{
//Trace.TraceInformation("exclusive section");
//}
return null;
}
....
}
除非锁定块被取消注释,否则它的工作完全正常。 此时_lock字段停止初始化 - _lock为null,可以使用调试器或TraceInformation进行验证。 实际上,一旦存在锁定块,对于任何字段使用静态构造函数的内联和初始化都会停止工作。 是什么让它更奇怪,这只发生在这个特定的类中。我无法在应用程序中的任何其他静态类中重现它。
我觉得我在这里遗漏了一些令人尴尬的事情。
[编辑]
事实证明(我应该首先提供一个更完整的例子..)其中一个字段变量在内部引用了GObjContextHelper.GetObjContext()。修复此循环引用后,一切都按预期工作。
我仍然会理解在静态类初始化期间发生的事情的解释,其中字段变量是一个在其构造函数中引用上述静态类的对象。为什么lock语句对变量初始化顺序有这样的影响。
更详细的例子:
public static class GObjContextHelper
{
private static TestService testService = new TestService();
private static readonly object _lock = new object();
public static GObjContext GetObjContext()
{
Trace.TraceInformation("_lock: " + _lock);
// _lock is properly initialized if this lock block is commented out.
// otherwise _lock is null
//lock (_lock)
//{
//}
return null;
}
public static object Account { get { return testService.GetCurrentAccount(); } }
}
public class TestService
{
GObjContext context;
public AccountService()
{
context = GObjContextHelper.GetObjContext();
}
public object GetCurrentAccount()
{
return null;
}
}
答案 0 :(得分:1)
你绝对可以通过以下方式来解决这个问题:
public static class GObjContextHelper
{
private static object _lock;
public static GObjContext GetObjContext()
{
Trace.TraceInformation("_lock: " + _lock);
lock (GetLockObject())
{
Trace.TraceInformation("exclusive section");
}
return null;
}
private static object GetLockObject()
{
if (_lock == null)
{
_lock = new object();
}
return _lock;
}
....
}
答案 1 :(得分:0)
如果想要确定性地初始化静态字段,则需要一个静态构造函数:
public static class GObjContextHelper
{
private static readonly object _lock;
static GObjContextHelper()
{
_lock = new object();
}
}
您也可以通过指定静态构造函数来强制字段初始化。这告诉c#编译器你的类型不要用beforefieldinit CIL属性标记。
public static class GObjContextHelper
{
private static readonly object _lock = new object();
static GObjContextHelper()
{
}
}