C# 多次调用PreApplicationStartMethod
由C# 多次调用PreApplicationStartMethod,c#,double-checked-locking,C#,Double Checked Locking,由PreApplicationStartMethod属性修饰的程序集中的类中的方法意味着在触发Application\u Start事件之前调用。 例如,这就是BuildManager在编译页面、控件或视图时了解要引用哪些程序集(除了web应用程序中的程序集)的方法。 期望只调用一次指出的方法是很自然的——毕竟它是初始化过程的一部分,通常每个应用程序只调用一次。(我只会提到创建数据库的尝试两次!!) 添加一些跟踪调用后,我发现该方法(不总是,有时!)被调用了两次。 为了避免这种情况,我在类中添加
PreApplicationStartMethod
属性修饰的程序集中的类中的方法意味着在触发Application\u Start
事件之前调用。
例如,这就是BuildManager
在编译页面、控件或视图时了解要引用哪些程序集(除了web应用程序中的程序集)的方法。期望只调用一次指出的方法是很自然的——毕竟它是初始化过程的一部分,通常每个应用程序只调用一次。(我只会提到创建数据库的尝试两次!!)
添加一些跟踪调用后,我发现该方法(不总是,有时!)被调用了两次。 为了避免这种情况,我在类中添加了一个布尔字段,以防止类似这样的多次调用:
private static bool initialzed;
public static void Initialize()
if (PreApplicationInit.initialzed == false)
{
// perform the initialization here
// ...
PreApplicationInit.initialzed = true;
}
}
private static readonly object SyncRoot = new Object();
private static bool initialzed;
public static void Initialize()
{
if (PreApplicationInit.initialzed == false)
{
lock (PreApplicationInit.SyncRoot)
{
if (PreApplicationInit.initialzed == false)
{
// perform the initialization here
// ...
PreApplicationInit.initialzed = true;
}
}
}
}
令我惊讶的是,这种方法又被调用了两次。一个明显的怀疑是它是在两个不同的线程上调用的(尽管这在初始化代码中有点意义)。
是解决此类问题的一个显而易见的方法,因此我对代码进行了如下更改:
private static bool initialzed;
public static void Initialize()
if (PreApplicationInit.initialzed == false)
{
// perform the initialization here
// ...
PreApplicationInit.initialzed = true;
}
}
private static readonly object SyncRoot = new Object();
private static bool initialzed;
public static void Initialize()
{
if (PreApplicationInit.initialzed == false)
{
lock (PreApplicationInit.SyncRoot)
{
if (PreApplicationInit.initialzed == false)
{
// perform the initialization here
// ...
PreApplicationInit.initialzed = true;
}
}
}
}
真正让这成为问题的是,代码是从本机代码调用的。t这是来自跟踪点的$CALLER:
[Native to Managed Transition]
所以,我的问题很明显,我想:什么(以及更重要的原因!)多次调用表示在
Application\u Start
event之前调用的方法?如果它是一个web应用程序,那么应用程序池中可能有多个实例。尝试更改IIS设置-将工作实例池大小减少到1,看看会发生什么。你有C++全局变量吗?在非托管DLL加载时初始化C++静态。对于C++对象之间的循环依赖性,初始化顺序是未定义的(参见静态初始化顺序FASASCO)。尝试使用调试器检查“奇数”双初始化来自何处。@Baldrick:是的,这是可能的,但不会发生。这个应用程序仍然在测试,请求来自一个浏览器,单个标签。@ Alois Kraus:不,没有C++。静态Ctor本身就是线程安全的。clr将锁定对它的访问。如果托管静态之间存在循环依赖关系,则可能会发生这种双重初始化。在这种情况下,您可以看到一个部分初始化的对象。看见