0

A method in a class in an assembly decorated by PreApplicationStartMethod attribute is meant to be called before Application_Start event is fired. For example, this is how BuildManager gets to know what assemblies (in addition to ones in the web application) to reference when compiling a page, a control, or a view.
It is quite natural to expect the pointed out method to be called only once -- after all it it part of an initialization process, which normally occurs only once per application. (I will only mention an attempt to create a database twice!!)
After adding some trace calls I discovered that the method (not always, sometimes!) is called twice. In order to avoid this I added a boolean field to the class to prevent multiple calls like this:

   private static bool initialzed;

   public static void Initialize()

        if (PreApplicationInit.initialzed == false)
        {
            // perform the initialization here
            // ...
            PreApplicationInit.initialzed = true;
        }
    }

To my surprise the method got called twice again. An obvious suspicion was that it is called on two different threads (despite this makes a little sense in an initialization code). Double-check locking was an obvious solution to such a problem, so I changed the code like this:

   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;
                }
            }
        }
    }

What is really making this an issue is the fact that the code is called from native code. Tthis is the $CALLER from a tracepoint:

[Native to Managed Transition]

So, my question is obvious, I guess: what (and more important why!) invokes a method denoted to be called before Application_Start event more than once?

Alexander Christov
  • 9,625
  • 7
  • 43
  • 58
  • If it's a web app, it's possible there could be more than one instance in the application pool. Try changing your IIS settings - reduce the worker instance pool size to 1 and see what happens. – Baldrick Sep 21 '14 at 08:34
  • Are you having C++ global variables? The C++ statics are initialized when the unmanaged dll is loaded. For cyclic dependencies between C++ objects the initialization order is undefined (see static initialization order fiasco). Try using a debugger to check where the "odd" double init is coming from. – Alois Kraus Sep 21 '14 at 08:35
  • @Baldrick: yes, it is possible, but does not happen. The app is still tested, requests are from a single browser, single tab. – Alexander Christov Sep 21 '14 at 08:40
  • @Alois Kraus: no, no C++ whatsoever. – Alexander Christov Sep 21 '14 at 08:41
  • The static ctor is thread safe in itself. The clr will lock access to it. Such a double init could happen if you have cyclic dependencies between managed statics. In that case you can see a partially initialized object. See http://codeblog.jonskeet.uk/2012/04/07/type-initializer-circular-dependencies/ – Alois Kraus Sep 21 '14 at 08:45
  • @AloisKraus: yes, static ctors are a natural alternative to double-check locking. However, my code (PreApplicationStartMethod-ed) is called by native code, most probably one that IIS hosts. This makes me think that the situation you describe is quite alike. Moreover, there's a single static ctor in the code, which does not reference any code outside the class, defining the method in question. And yes, I read the article -- it describes interesting, yet quite an awkward scenario, I guess... Any other ideas? Let me remind again: what calls the PreApp... method, Initialize() in my case? – Alexander Christov Sep 21 '14 at 09:14
  • I cannot answer the question who calls Initializes. When guessing does not help you should start debugging. – Alois Kraus Sep 21 '14 at 12:20

0 Answers0