Global - Application_OnStart question

Discussion in 'ASP .Net' started by Shiv Kumar, Jan 13, 2004.

  1. Shiv Kumar

    Shiv Kumar Guest

    I see that the Application_OnStart event is fired only once for a certain application.

    I'm interested in creating a "global" object (an object that will be available to all requests for the application). I thought I could use this event to create an instance of my object.

    I find that the event does get fired and an instance is created. However, when I reference this object from a page it is null. What gives?

    What is the recommended way to declare, create etc. my class such that an single instance is created (application wide) and that all my pages have access to this object.

    I don't mind if I have to make this object thread-safe and a singleton either. I'd just like to know the recommended way and if this is at all possible.

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Shiv Kumar, Jan 13, 2004
    #1
    1. Advertising

  2. If you want a class to be global to the Application, you have to put it into
    a global memory area for the Application, such as the Application Cache. The
    Application Cache is a Collection, and the elements in it are global to the
    entire Application. Be aware, however, that the Application Cache has
    expiration, and you need to handle the expiration of the elements in it.

    --
    HTH,
    Kevin Spencer
    ..Net Developer
    Microsoft MVP
    Big things are made up
    of lots of little things.

    "Shiv Kumar" <> wrote in message
    news:#...
    I see that the Application_OnStart event is fired only once for a certain
    application.

    I'm interested in creating a "global" object (an object that will be
    available to all requests for the application). I thought I could use this
    event to create an instance of my object.

    I find that the event does get fired and an instance is created. However,
    when I reference this object from a page it is null. What gives?

    What is the recommended way to declare, create etc. my class such that an
    single instance is created (application wide) and that all my pages have
    access to this object.

    I don't mind if I have to make this object thread-safe and a singleton
    either. I'd just like to know the recommended way and if this is at all
    possible.

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Kevin Spencer, Jan 13, 2004
    #2
    1. Advertising

  3. Shiv Kumar

    Martin Guest

    > I find that the event does get fired and an instance is created.
    > However, when I reference this object from a page it is null.


    Are you sure you are referencing the same thing you created earlier? If you create an object and put it in an application variable like

    Application["MyObject] = new MyObject();

    you should be able to access it from any page like so:

    Application.Lock();
    MyObject obj = (MyObject)Application["MyObject];
    Application.UnLock();


    Application_Start is a perfect spot to create your object. An explanation for your problem could be that the code in Application_Start fails somewhere before the creation of your object. You may want to try to put your creation statement first and try again.

    Martin.

    "Shiv Kumar" <> wrote in message news:%...
    I see that the Application_OnStart event is fired only once for a certain application.

    I'm interested in creating a "global" object (an object that will be available to all requests for the application). I thought I could use this event to create an instance of my object.

    I find that the event does get fired and an instance is created. However, when I reference this object from a page it is null. What gives?

    What is the recommended way to declare, create etc. my class such that an single instance is created (application wide) and that all my pages have access to this object.

    I don't mind if I have to make this object thread-safe and a singleton either. I'd just like to know the recommended way and if this is at all possible.

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Martin, Jan 13, 2004
    #3
  4. Shiv Kumar

    Scott Allen Guest

    The singleton pattern is a well accepted and reusable way to create
    your object. If it is inside the same assembly (project) as all your
    pages they will be able to reference the object without even lookin in
    Application state.

    --
    Scott
    http://www.OdeToCode.com

    On Tue, 13 Jan 2004 05:12:12 -0500, "Shiv Kumar"
    <> wrote:

    >I see that the Application_OnStart event is fired only once for a certain application.
    >
    >I'm interested in creating a "global" object (an object that will be available to all requests for the application). I thought I could use this event to create an instance of my object.
    >
    >I find that the event does get fired and an instance is created. However, when I reference this object from a page it is null. What gives?
    >
    >What is the recommended way to declare, create etc. my class such that an single instance is created (application wide) and that all my pages have access to this object.
    >
    >I don't mind if I have to make this object thread-safe and a singleton either. I'd just like to know the recommended way and if this is at all possible.
     
    Scott Allen, Jan 13, 2004
    #4
  5. Shiv Kumar

    Shiv Kumar Guest

    Shiv Kumar, Jan 13, 2004
    #5
  6. Shiv Kumar

    Shiv Kumar Guest

    >Are you sure you are referencing the same thing you created earlier?

    Yes. The Global object has a property of my class type. So from within a Page I refer to it as Global.xxxx (Of course ApplicationInstance has been type casted here).

    Even a regular int variable is incremented in Application_OnStart but when I read it from a page it is zero (not incremented). But I can see the execution go into Application_OnStart, create my object (or increment the count variable).

    The issue it seems is that the Global object is instantiated twice by the ASP.NET framework. The first time the Application_OnStart event is fired as well. But the next time it is not. It looks like the previous reference of Global is over written new one has not had at shot at the Application_OnStart event.

    >Application["MyObject] = new MyObject();


    I haven't tried this...

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Shiv Kumar, Jan 13, 2004
    #6
  7. Shiv Kumar

    Shiv Kumar Guest

    Thanks Scott for the confirmation. However, what's the best place to
    instantiate an instance? Granted, as a singleton my question then becomes
    moot. Just seeing that the Application_OnStart event gets fired only once..

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Shiv Kumar, Jan 13, 2004
    #7
  8. Shiv Kumar

    Martin Guest

    Shiv,

    >> Are you sure you are referencing the same thing you created earlier?


    > Yes. The Global object has a property of my class type. So from
    > within a Page I refer to it as Global.xxxx (Of course ApplicationInstance
    > has been type casted here).


    Show us the property get code.

    > The issue it seems is that the Global object is instantiated twice by the
    > ASP.NET framework. The first time the Application_OnStart event is fired
    > as well. But the next time it is not. It looks like the previous reference of
    > Global is over written new one has not had at shot at the
    > Application_OnStart event.


    I must say I had a similar experience the other day when I was trying to figure out what was happening. I created an XmlDocument in the application object which I had updated and written to file by application and session events. At one point I seemed to have two different documents, triggered by two different browser sessions. I could tell by the toggling contents of the disk file. I then made the XmlDocument member static just to be sure I would have only one but it should of course not matter if application were a singleton. Which it should be... Which you and I found out it is not at all times...

    It may again lead back to the problem I had. Make absolutely sure you have no failing code in any of the application events, preferably clear them all and start to buildup again piece by piece, doing tests in between additions.

    Martin.
     
    Martin, Jan 13, 2004
    #8
  9. Shiv Kumar

    Shiv Kumar Guest

    Martin,

    The property accessor is normal :) It returns the private variable that was assigned in the Application_OnStart event. Are you suggesting I use the Application's hashtable to store my instance?

    protected void Application_Start(Object sender, EventArgs e)

    {

    count++

    }

    public int Count { get { return count; } }


    My application is a bare bones app. I'm trying to wrap my head around some of the ASP.NET nuances so besides an int variable I have a simple object. That's it.

    Even in the case above, Count will be Zero. I can see it being incremented the first time, but when I look at from within a page its zero.

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Shiv Kumar, Jan 13, 2004
    #9
  10. Shiv Kumar

    Martin Guest

    > The property accessor is normal :) It returns the private variable that was
    > assigned in the Application_OnStart event. Are you suggesting I use the
    > Application's hashtable to store my instance?


    protected void Application_Start(Object sender, EventArgs e)

    {

    count++

    }

    public int Count { get { return count; } }


    I was suggesting you didn't know how to use properties in C#. I take it you declared the member itself as

    private int count;

    somewhere up in your application class. I would also say it should work. Why not post the entire "bare bones" application class? This is getting interesting.
     
    Martin, Jan 13, 2004
    #10
  11. Shiv Kumar

    Shiv Kumar Guest

    Here is the code from by Global.asax.cs file

    public class Global : System.Web.HttpApplication

    {

    /// <summary>

    /// Required designer variable.

    /// </summary>

    private System.ComponentModel.IContainer components = null;

    private int count = 0;

    public Global()

    {

    InitializeComponent();

    }

    public int Count { get { return count; } }


    protected void Application_Start(Object sender, EventArgs e)

    {

    count++;

    }



    Here is the code from the Page

    private void Page_Load(object sender, System.EventArgs e)

    {

    Label1.Text = ((WebApplication1.Global)Context.ApplicationInstance).Count.ToString();

    }


    I can see that the count variable is getting incremented once. But the label on the page displays a zero.

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Shiv Kumar, Jan 13, 2004
    #11
  12. Shiv Kumar

    Martin Guest

    Shiv,

    You're right, I am experiencing the same thing here. If I increment count in
    Session_Start as well and I debug, it appears that while in
    Application_Start count is incremented but when it enters Session_Start the
    value is already reset. If you initialize it to 100 you will see it flips
    back to 100.

    If you make count static, it works as expected (!). It seems we have more
    than one application. Here's more proof.

    Declare this in Global:

    private static Global theApp = null;

    Put this in Application_Start:

    theApp = this;

    Put this in Session_Start:

    Boolean b = theApp.Equals(this);

    and debug. You'll see that our one-and-only would-be-singleton application
    object suffers from serious multiple personality disorder.


    It looks like the application is recreated after Application_Start. Not nice
    at all, looks like a serious bug to me. Now I'm sure some Microsoft employee
    will respond claiming this is "behavior by design". I am very much
    interested in the design philosophy at this point.

    Martin.
     
    Martin, Jan 13, 2004
    #12
  13. Shiv Kumar

    Scott Allen Guest

    As you predicted, this behavior is by design. :)

    There is a pool of HttpApplication objects that ASP.NET uses to
    service requests. The runtime pairs each incoming request with an
    HttpApplication object, and the object services the request until the
    response is complete, then the object returns to the pool.

    The runtime invokes the Init method on ALL HttpApplication objects,
    while Applicaiton_OnStart only fires once and on the first
    HttpApplication object in the pool.

    For more info, see Working with HttpApplication Instances:
    http://msdn.microsoft.com/library/d.../cpconworkingwithhttpapplicationinstances.asp

    --
    Scott
    http://www.OdeToCode.com

    On Wed, 14 Jan 2004 00:37:10 +0100, "Martin" <>
    wrote:

    >Shiv,
    >
    >You're right, I am experiencing the same thing here. If I increment count in
    >Session_Start as well and I debug, it appears that while in
    >Application_Start count is incremented but when it enters Session_Start the
    >value is already reset. If you initialize it to 100 you will see it flips
    >back to 100.
    >
    >If you make count static, it works as expected (!). It seems we have more
    >than one application. Here's more proof.
    >
    >Declare this in Global:
    >
    >private static Global theApp = null;
    >
    >Put this in Application_Start:
    >
    >theApp = this;
    >
    >Put this in Session_Start:
    >
    >Boolean b = theApp.Equals(this);
    >
    >and debug. You'll see that our one-and-only would-be-singleton application
    >object suffers from serious multiple personality disorder.
    >
    >
    >It looks like the application is recreated after Application_Start. Not nice
    >at all, looks like a serious bug to me. Now I'm sure some Microsoft employee
    >will respond claiming this is "behavior by design". I am very much
    >interested in the design philosophy at this point.
    >
    >Martin.
    >
     
    Scott Allen, Jan 14, 2004
    #13
  14. Shiv Kumar

    Shiv Kumar Guest

    Scott I think both Martin and I are fully aware of the explanation you gave
    :)

    But that's not the point. The Application_Start event does fire only once
    (as expected) however, this is the sequence of things that happen.

    1. Global's constructor is called.
    2. The Global descendant's constructor is called. (this is the class that
    ASP.NET creates on-the-fly

    [System.Runtime.CompilerServices.CompilerGlobalScopeAttribute()]

    public class Global_asax : WebApplication1.Global {


    private static bool __initialized = false;


    public Global_asax() {

    if ((ASP.Global_asax.__initialized == false)) {

    ASP.Global_asax.__initialized = true;

    }

    }

    }



    3. ___initialized is false this time and so it is set to true.

    4. Application_Start is fired.

    5. Global's constructor is called again! (Not sure why, but all fields are
    initialized since it's a new instance. And this is where there problem is
    and the reason the problem exists)

    6. Global's descendant's constructor is called again (this is expected since
    it is really the descendant being re-created that causes the ancestor's
    constructor to be called)

    7. This time

    __initialized is true

    8. But this time Application_Start is not fired as a result we have a fully
    reinitialized global instance as a result the property Count is zero.


    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Shiv Kumar, Jan 14, 2004
    #14
  15. Shiv Kumar

    Shiv Kumar Guest

    > and debug. You'll see that our one-and-only would-be-singleton application
    > object suffers from serious multiple personality disorder.


    Exactly right. Two instances of Global's descendant are being created not
    just one.

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Shiv Kumar, Jan 14, 2004
    #15
  16. Shiv Kumar

    Martin Guest

    > There is a pool of HttpApplication objects that ASP.NET uses to
    > service requests. The runtime pairs each incoming request with an
    > HttpApplication object, and the object services the request until the
    > response is complete, then the object returns to the pool.
    >
    > The runtime invokes the Init method on ALL HttpApplication objects,
    > while Applicaiton_OnStart only fires once and on the first
    > HttpApplication object in the pool.


    Which makes it effectively a static constructor in .NET programming
    semantics. This is not reflected by the C# code and therefor utterly wrong.
    One cannot expect a programmer to learn a language and then accept the fact
    that one particular runtime environment (ASP.NET) haves its own way with the
    semantics. I consider this very serious.

    > For more info, see Working with HttpApplication Instances:
    >

    http://msdn.microsoft.com/library/d.../cpconworkingwithhttpapplicationinstances.asp

    I understand we should override Init and Dispose to get the very behavior we
    were up until now expecting from Application_Start and Application_End
    (thank you very much for this brilliant nomenclature). And yet, an
    application is not really an application. We must either go back to the ASP
    1.0 days and work with application variables exclusively (which still seem
    to be shared across different application objects) or declare everything in
    application static to fix what the ASP.NET team screwed up. It sucks! And it
    is likely causing a lot of headaches in the ASP.NET community.

    Martin.


    > >Shiv,
    > >
    > >You're right, I am experiencing the same thing here. If I increment count

    in
    > >Session_Start as well and I debug, it appears that while in
    > >Application_Start count is incremented but when it enters Session_Start

    the
    > >value is already reset. If you initialize it to 100 you will see it flips
    > >back to 100.
    > >
    > >If you make count static, it works as expected (!). It seems we have more
    > >than one application. Here's more proof.
    > >
    > >Declare this in Global:
    > >
    > >private static Global theApp = null;
    > >
    > >Put this in Application_Start:
    > >
    > >theApp = this;
    > >
    > >Put this in Session_Start:
    > >
    > >Boolean b = theApp.Equals(this);
    > >
    > >and debug. You'll see that our one-and-only would-be-singleton

    application
    > >object suffers from serious multiple personality disorder.
    > >
    > >
    > >It looks like the application is recreated after Application_Start. Not

    nice
    > >at all, looks like a serious bug to me. Now I'm sure some Microsoft

    employee
    > >will respond claiming this is "behavior by design". I am very much
    > >interested in the design philosophy at this point.
    > >
    > >Martin.
    > >

    >
     
    Martin, Jan 14, 2004
    #16
  17. Shiv Kumar

    Scott Allen Guest

    Shiv:

    Based on your description, it appears you are still thinking of Global
    as a singleton, but it is not.

    >5. Global's constructor is called again! (Not sure why, but all fields are
    >initialized since it's a new instance. And this is where there problem is
    >and the reason the problem exists)
    >


    If you have a breakpoint set on the constructor for Global, you will
    see it "called again" because there is more than one instance of
    Global used by the ASP.NET runtime. There may be 5 running at a time,
    maybe 100 - the point is there will be more than 1.

    You are only initializing your "count" variable in one of the many
    HttpApplication objects.


    HTH,


    --s
    --
    Scott
    http://www.OdeToCode.com
     
    Scott Allen, Jan 14, 2004
    #17
  18. Shiv Kumar

    Scott Allen Guest

    Martin:

    I agree it is confusing because we tend to think of something with
    "application" in the name as being a singleton for our application.
    But see inline comments.


    On Wed, 14 Jan 2004 12:28:08 +0100, "Martin" <>
    wrote:

    <snip>
    >> The runtime invokes the Init method on ALL HttpApplication objects,
    >> while Applicaiton_OnStart only fires once and on the first
    >> HttpApplication object in the pool.

    >
    >Which makes it effectively a static constructor in .NET programming
    >semantics. This is not reflected by the C# code and therefor utterly wrong.
    >One cannot expect a programmer to learn a language and then accept the fact
    >that one particular runtime environment (ASP.NET) haves its own way with the
    >semantics. I consider this very serious.
    >


    It is definably not a static constructor - it is not even a static
    method. The docs are quite clear that you should only use
    Application_OnStart to modify variables that are shared (static)
    amongst all the instances.

    >> For more info, see Working with HttpApplication Instances:
    >>

    >http://msdn.microsoft.com/library/d.../cpconworkingwithhttpapplicationinstances.asp
    >
    >I understand we should override Init and Dispose to get the very behavior we
    >were up until now expecting from Application_Start and Application_End
    >(thank you very much for this brilliant nomenclature). And yet, an
    >application is not really an application. We must either go back to the ASP
    >1.0 days and work with application variables exclusively (which still seem
    >to be shared across different application objects) or declare everything in
    >application static to fix what the ASP.NET team screwed up. It sucks! And it
    >is likely causing a lot of headaches in the ASP.NET community.
    >


    If you want to keep a simple variable like count around, one of the
    many places you could keep the variable is in application state, i.e.

    Application["count"] = 0;

    That is exactly what application state is designed for by being a
    global, thread safe, and efficient container. I don't view this as
    some sort of "fall back to the old days" as it is still a viable
    solution.

    Alternatively you can build a singleton class. Here is a great
    reference:
    http://www.yoda.arachsys.com/csharp/singleton.html

    I can understand where the class name is confusing, but if you want
    singleton behavior there is just no avoiding the static keyword.

    --s
    --
    Scott
    http://www.OdeToCode.com
     
    Scott Allen, Jan 14, 2004
    #18
  19. Shiv Kumar

    Martin Guest

    Scott,

    > I agree it is confusing because we tend to think of something with
    > "application" in the name as being a singleton for our application.


    The main reason for my fiece response is that I feel tricked by these
    constructs. Some things one just takes for granted based on experience and
    the assumption that there is "one application object in one's application"
    is one of those things. It may all be well documented, you just assume that
    1 + 1 equals 2 regardless the environment.

    Once you are aware of them a couple of inconsistencies are not that hard to
    live with. It would have meant a lot if Visual Studio would have generated
    comments that warn us about these issues, like it does for generated
    skeleton code in MFC applications. An update of the ASP.NET Web Application
    wizard would be nice.

    Martin.
     
    Martin, Jan 14, 2004
    #19
  20. Shiv Kumar

    Shiv Kumar Guest

    Scott,

    Yes, I see how my previous post might lead you to believe that I expect
    Global to be a singleton. But I don't.

    Let me ask the question this way. What would one use the Application_Start
    event for? I'm not really trying to do something like increment a count of a
    variable :)

    --
    Shiv R. Kumar
    http://www.matlus.com
     
    Shiv Kumar, Jan 14, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. yop
    Replies:
    4
    Views:
    441
  2. Marek

    Application_OnStart event

    Marek, May 9, 2004, in forum: ASP .Net
    Replies:
    8
    Views:
    491
    Scott Allen
    May 11, 2004
  3. =?Utf-8?B?QmlsbCBIZWNrbGU=?=

    Application_OnStart

    =?Utf-8?B?QmlsbCBIZWNrbGU=?=, Aug 16, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    347
    =?Utf-8?B?QnJhZCBRdWlubg==?=
    Aug 16, 2004
  4. =?Utf-8?B?TWlrZSBMb2dhbg==?=

    HTTP Module attaching to Application_OnStart

    =?Utf-8?B?TWlrZSBMb2dhbg==?=, Dec 17, 2004, in forum: ASP .Net
    Replies:
    5
    Views:
    4,713
    Steven Cheng[MSFT]
    Dec 31, 2004
  5. archana
    Replies:
    1
    Views:
    345
Loading...

Share This Page