Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/416.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多次调用PreApplicationStartMethod_C#_Double Checked Locking - Fatal编程技术网

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将锁定对它的访问。如果托管静态之间存在循环依赖关系,则可能会发生这种双重初始化。在这种情况下,您可以看到一个部分初始化的对象。看见