Static Variable Reference in Web Service?

Discussion in 'ASP .Net Web Services' started by depalau@bemis.com, Oct 12, 2006.

  1. Guest

    I'm running into some issues on maintaining a static variable across
    the lifetime of a web service and I was wondering if anyone could help.

    Background:

    We have developed a C#/1.1 web service running on IIS 5/6 that
    interfaces with a 3rd party DLL referenced by using the DLLImport
    attribute.

    Interacting with this 3rd party software through this dll requires an
    initialization call to it which prepares it for subsequent functional
    calls. Once all of our functional calls are made, we need to call
    another dll function to close it's resources (it is a license based
    application).

    Due to the amount of resources needed by this 3rd party software and
    the amount of web service calls made against it, it is recommened that
    we only initialize it once and 'close' it only when our web service
    gets recycled by IIS after a period of inactivity. Initializing this
    dll returns a number that we use to perform any functionality call and
    to close the software (serverID).

    I have placed the call to initialize in the global.asax
    Application_Start method and the call to close in the Application_End
    method.

    Our code looks a little like:

    public class 3rdParty
    {

    public static short serverID;

    public static void Initialize()
    {
    Close();
    serverID = OpenServer();
    }

    public static void Close()
    {
    if (serverID > 0)
    {
    CloseServer(serverID);
    }
    }

    [DllImport("3rdParty2.DLL", EntryPoint ="OpenServer",
    ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true)]
    private static extern short OpenServer();

    [DllImport("PCMSRV32.DLL", EntryPoint = "CloseServer",
    ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true)]
    private static extern int CloseServer(short serverID);
    }


    In the global.asax file:

    protected void Application_Start(Object sender, EventArgs e)
    {
    3rdParty.Initialize();
    }

    protected void Application_End(Object sender, EventArgs e)
    {
    3rdParty.Close();
    }


    What is happening is that if we have a lull in access to the web
    service, IIS will recycle the app domain. The next time the web
    service gets started up, it will attempt to call OpenServer() again,
    but since CloseServer() was never called, this 3rd party software won't
    accept another OpenServer call until it is closed with the previous
    serverID.

    Am I going about this the right way by having a static serverID
    variable? Should I be storing this value somewhere else for access?

    Any input would be greatly appreciated.

    Thanks,

    -David
    , Oct 12, 2006
    #1
    1. Advertising

  2. the dll is actually loaded by the aspnet worker process that hosts the
    appdomain. a normal recycle load a new appdomain, then unloads the old
    domain. when this happen the second load will be called before the first
    unload.

    you should write another c/c++ dll that manages the open and close (it can
    use a static).

    -- bruce (sqlwork.com)

    <> wrote in message
    news:...
    > I'm running into some issues on maintaining a static variable across
    > the lifetime of a web service and I was wondering if anyone could help.
    >
    > Background:
    >
    > We have developed a C#/1.1 web service running on IIS 5/6 that
    > interfaces with a 3rd party DLL referenced by using the DLLImport
    > attribute.
    >
    > Interacting with this 3rd party software through this dll requires an
    > initialization call to it which prepares it for subsequent functional
    > calls. Once all of our functional calls are made, we need to call
    > another dll function to close it's resources (it is a license based
    > application).
    >
    > Due to the amount of resources needed by this 3rd party software and
    > the amount of web service calls made against it, it is recommened that
    > we only initialize it once and 'close' it only when our web service
    > gets recycled by IIS after a period of inactivity. Initializing this
    > dll returns a number that we use to perform any functionality call and
    > to close the software (serverID).
    >
    > I have placed the call to initialize in the global.asax
    > Application_Start method and the call to close in the Application_End
    > method.
    >
    > Our code looks a little like:
    >
    > public class 3rdParty
    > {
    >
    > public static short serverID;
    >
    > public static void Initialize()
    > {
    > Close();
    > serverID = OpenServer();
    > }
    >
    > public static void Close()
    > {
    > if (serverID > 0)
    > {
    > CloseServer(serverID);
    > }
    > }
    >
    > [DllImport("3rdParty2.DLL", EntryPoint ="OpenServer",
    > ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true)]
    > private static extern short OpenServer();
    >
    > [DllImport("PCMSRV32.DLL", EntryPoint = "CloseServer",
    > ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true)]
    > private static extern int CloseServer(short serverID);
    > }
    >
    >
    > In the global.asax file:
    >
    > protected void Application_Start(Object sender, EventArgs e)
    > {
    > 3rdParty.Initialize();
    > }
    >
    > protected void Application_End(Object sender, EventArgs e)
    > {
    > 3rdParty.Close();
    > }
    >
    >
    > What is happening is that if we have a lull in access to the web
    > service, IIS will recycle the app domain. The next time the web
    > service gets started up, it will attempt to call OpenServer() again,
    > but since CloseServer() was never called, this 3rd party software won't
    > accept another OpenServer call until it is closed with the previous
    > serverID.
    >
    > Am I going about this the right way by having a static serverID
    > variable? Should I be storing this value somewhere else for access?
    >
    > Any input would be greatly appreciated.
    >
    > Thanks,
    >
    > -David
    >
    bruce barker \(sqlwork.com\), Oct 12, 2006
    #2
    1. Advertising

  3. David Palau Guest

    Thanks for responding.

    I'm a little confused, with this new DLL you mention, who would host
    that? Wouldn't it still be the aspnet worker process?


    I should have been a little clearer in my description of how our
    project is set up:


    We have an assembly (MyCompany.MyApp.WebService) that contains the web
    service that points to another assembly (MyCompany.MyApp.Library) that
    contains the 3rdParty class that holds the static variable and static
    DLLImport references to the 3rd party supplied dll (3rdParty.dll).


    How would adding another C/C++ dll that contains the 3rd party
    interfaces still be around if the reference to it from the web service
    assembly goes away? And why C/C++?


    Sorry if I'm misunderstanding certain things, I don't have much
    experience in maintaining information in web service apps that need to
    stick around like this.
    David Palau, Oct 12, 2006
    #3
  4. <> wrote in message
    news:...
    > I'm running into some issues on maintaining a static variable across
    > the lifetime of a web service and I was wondering if anyone could help.
    >
    > Background:
    >
    > We have developed a C#/1.1 web service running on IIS 5/6 that
    > interfaces with a 3rd party DLL referenced by using the DLLImport
    > attribute.
    >
    > Interacting with this 3rd party software through this dll requires an
    > initialization call to it which prepares it for subsequent functional
    > calls. Once all of our functional calls are made, we need to call
    > another dll function to close it's resources (it is a license based
    > application).
    >
    > Due to the amount of resources needed by this 3rd party software and
    > the amount of web service calls made against it, it is recommened that
    > we only initialize it once and 'close' it only when our web service
    > gets recycled by IIS after a period of inactivity. Initializing this
    > dll returns a number that we use to perform any functionality call and
    > to close the software (serverID).
    >
    > I have placed the call to initialize in the global.asax
    > Application_Start method and the call to close in the Application_End
    > method.
    >
    > Our code looks a little like:
    >
    > public class 3rdParty
    > {
    >
    > public static short serverID;
    >
    > public static void Initialize()
    > {
    > Close();
    > serverID = OpenServer();
    > }
    >
    > public static void Close()
    > {
    > if (serverID > 0)
    > {
    > CloseServer(serverID);
    > }
    > }
    >
    > [DllImport("3rdParty2.DLL", EntryPoint ="OpenServer",
    > ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true)]
    > private static extern short OpenServer();
    >
    > [DllImport("PCMSRV32.DLL", EntryPoint = "CloseServer",
    > ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true)]
    > private static extern int CloseServer(short serverID);
    > }
    >
    >
    > In the global.asax file:
    >
    > protected void Application_Start(Object sender, EventArgs e)
    > {
    > 3rdParty.Initialize();
    > }
    >
    > protected void Application_End(Object sender, EventArgs e)
    > {
    > 3rdParty.Close();
    > }
    >
    >
    > What is happening is that if we have a lull in access to the web
    > service, IIS will recycle the app domain. The next time the web
    > service gets started up, it will attempt to call OpenServer() again,
    > but since CloseServer() was never called, this 3rd party software won't
    > accept another OpenServer call until it is closed with the previous
    > serverID.
    >
    > Am I going about this the right way by having a static serverID
    > variable? Should I be storing this value somewhere else for access?
    >
    > Any input would be greatly appreciated.



    First of all, you said that CloseServer is never called. Remove the
    conditional in Close() and see what happens. If it's still not getting
    called, it may be because Application_End is not being called.

    Statics only last as long as the AppDomain does. When IIS recycles your
    AppDomain, any statics go away with it. I wonder how the third-party DLL
    manages not to be cleaned up when the AppDomain is terminated. Is any part
    of it a COM+ application or an application which runs in a separate process?

    BTW, it probably isn't a problem for you right now, but be aware that all
    threads in your web service can access the same static variable. If it's
    something that's being changed, then you need to use locks to serialize
    access to it. Otherwise you can have multiple requests all operating on the
    static at the same time.


    John
    John Saunders, Oct 13, 2006
    #4
  5. David Palau Guest

    I just noticed that I mis-typed our code in the DLLImport declarations,
    sorry. Here is what it is for clarity.

    > > Our code looks a little like:
    > >
    > > public class 3rdParty
    > > {
    > >
    > > public static short serverID;
    > >
    > > public static void Initialize()
    > > {
    > > Close();
    > > serverID = OpenServer();
    > > }
    > >
    > > public static void Close()
    > > {
    > > if (serverID > 0)
    > > {
    > > CloseServer(serverID);
    > > }
    > > }
    > >
    > > [DllImport("3rdParty.DLL", EntryPoint ="OpenServer",
    > > ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true)]
    > > private static extern short OpenServer();
    > >
    > > [DllImport("3rdParty.DLL", EntryPoint = "CloseServer",
    > > ExactSpelling = false, CharSet = CharSet.Ansi, SetLastError = true)]
    > > private static extern int CloseServer(short serverID);
    > > }
    > >
    > >
    > > In the global.asax file:
    > >
    > > protected void Application_Start(Object sender, EventArgs e)
    > > {
    > > 3rdParty.Initialize();
    > > }
    > >
    > > protected void Application_End(Object sender, EventArgs e)
    > > {
    > > 3rdParty.Close();
    > > }




    > First of all, you said that CloseServer is never called. Remove the
    > conditional in Close() and see what happens. If it's still not getting
    > called, it may be because Application_End is not being called.
    >


    Correct, I am not seeing the Close() call ever fire (unless I manually
    change the global.asax file or call IISRest or something like that
    which triggers this). I don't see it fire as part of the recycle
    process. I don't think the conditional will matter since a successful
    call to OpenServer will return a short larger than 0.

    > Statics only last as long as the AppDomain does. When IIS recycles your
    > AppDomain, any statics go away with it. I wonder how the third-party DLL
    > manages not to be cleaned up when the AppDomain is terminated. Is any part
    > of it a COM+ application or an application which runs in a separate process?


    I don't think the third-party DLL cleans up any open connections when
    it goes out of scope, they made it very clear that in order to free up
    licenses, you have to call CloseServer().

    > BTW, it probably isn't a problem for you right now, but be aware that all
    > threads in your web service can access the same static variable. If it's
    > something that's being changed, then you need to use locks to serialize
    > access to it. Otherwise you can have multiple requests all operating on the
    > static at the same time.


    For this application it is fine, in fact desirable, that we use the
    same serverID. What you say makes sense concerning the AppDomain going
    away blowing away all of the static variables. Do you have any
    suggestions on how to persist this data past that event? Write it to
    some file? Use some sort of session state? Thanks for the reply.
    David Palau, Oct 13, 2006
    #5
  6. "David Palau" <> wrote in message
    news:...
    >
    >
    >> First of all, you said that CloseServer is never called. Remove the
    >> conditional in Close() and see what happens. If it's still not getting
    >> called, it may be because Application_End is not being called.
    >>

    >
    > Correct, I am not seeing the Close() call ever fire (unless I manually
    > change the global.asax file or call IISRest or something like that
    > which triggers this). I don't see it fire as part of the recycle
    > process. I don't think the conditional will matter since a successful
    > call to OpenServer will return a short larger than 0.


    The reason I suggested removing the conditional is that it's an easy way to
    be sure.

    >> Statics only last as long as the AppDomain does. When IIS recycles your
    >> AppDomain, any statics go away with it. I wonder how the third-party DLL
    >> manages not to be cleaned up when the AppDomain is terminated. Is any
    >> part
    >> of it a COM+ application or an application which runs in a separate
    >> process?

    >
    > I don't think the third-party DLL cleans up any open connections when
    > it goes out of scope, they made it very clear that in order to free up
    > licenses, you have to call CloseServer().


    If it's open resources which are the problem, then perhaps your web service
    needs to have a higher isolation level in IIS. Maybe it should run in its
    own process. It really sounds like the kind of thing that shouldn't be
    running in-process in a production service.

    >> BTW, it probably isn't a problem for you right now, but be aware that all
    >> threads in your web service can access the same static variable. If it's
    >> something that's being changed, then you need to use locks to serialize
    >> access to it. Otherwise you can have multiple requests all operating on
    >> the
    >> static at the same time.

    >
    > For this application it is fine, in fact desirable, that we use the
    > same serverID. What you say makes sense concerning the AppDomain going
    > away blowing away all of the static variables. Do you have any
    > suggestions on how to persist this data past that event? Write it to
    > some file? Use some sort of session state? Thanks for the reply.


    You really need to get this old DLL running in it's own process. It sounds
    like the sort of thing that expects process deletion to clean up its messes.

    John
    John Saunders, Oct 13, 2006
    #6
  7. Rajat K Guest

    Hi,
    I faced a similar issue earlier this month where we were accessing a COM DLL
    from our web service. Every time a new (2nd instance) of the COM object was
    created, the web service 'froze'. Thus, not letting the web service create a
    2nd instance of the COM object.
    I read this article on MSDN, implemented it, and solved the issue.
    Take a look at it, this might resolve the issue you are facing:

    Running ASMX Web Services on STA Threads
    http://msdn.microsoft.com/msdnmag/issues/06/10/WickedCode/

    regards,
    Rajat Kaushish
    ----------------------
    "John Saunders" wrote:

    >
    > "David Palau" <> wrote in message
    > news:...
    > >
    > >
    > >> First of all, you said that CloseServer is never called. Remove the
    > >> conditional in Close() and see what happens. If it's still not getting
    > >> called, it may be because Application_End is not being called.
    > >>

    > >
    > > Correct, I am not seeing the Close() call ever fire (unless I manually
    > > change the global.asax file or call IISRest or something like that
    > > which triggers this). I don't see it fire as part of the recycle
    > > process. I don't think the conditional will matter since a successful
    > > call to OpenServer will return a short larger than 0.

    >
    > The reason I suggested removing the conditional is that it's an easy way to
    > be sure.
    >
    > >> Statics only last as long as the AppDomain does. When IIS recycles your
    > >> AppDomain, any statics go away with it. I wonder how the third-party DLL
    > >> manages not to be cleaned up when the AppDomain is terminated. Is any
    > >> part
    > >> of it a COM+ application or an application which runs in a separate
    > >> process?

    > >
    > > I don't think the third-party DLL cleans up any open connections when
    > > it goes out of scope, they made it very clear that in order to free up
    > > licenses, you have to call CloseServer().

    >
    > If it's open resources which are the problem, then perhaps your web service
    > needs to have a higher isolation level in IIS. Maybe it should run in its
    > own process. It really sounds like the kind of thing that shouldn't be
    > running in-process in a production service.
    >
    > >> BTW, it probably isn't a problem for you right now, but be aware that all
    > >> threads in your web service can access the same static variable. If it's
    > >> something that's being changed, then you need to use locks to serialize
    > >> access to it. Otherwise you can have multiple requests all operating on
    > >> the
    > >> static at the same time.

    > >
    > > For this application it is fine, in fact desirable, that we use the
    > > same serverID. What you say makes sense concerning the AppDomain going
    > > away blowing away all of the static variables. Do you have any
    > > suggestions on how to persist this data past that event? Write it to
    > > some file? Use some sort of session state? Thanks for the reply.

    >
    > You really need to get this old DLL running in it's own process. It sounds
    > like the sort of thing that expects process deletion to clean up its messes.
    >
    > John
    >
    >
    >
    Rajat K, Oct 23, 2006
    #7
    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. kookey
    Replies:
    3
    Views:
    20,743
    Andrew Thompson
    Aug 20, 2005
  2. Replies:
    6
    Views:
    693
    =?Utf-8?B?UmFqYXQgSw==?=
    Oct 23, 2006
  3. TheTravellingSalesman

    static reference in a non-static method

    TheTravellingSalesman, Aug 29, 2007, in forum: Java
    Replies:
    5
    Views:
    6,416
    TheTravellingSalesman
    Aug 30, 2007
  4. Leo Violette
    Replies:
    0
    Views:
    1,004
    Leo Violette
    Apr 17, 2009
  5. William Colls
    Replies:
    4
    Views:
    1,970
    Roedy Green
    Mar 20, 2012
Loading...

Share This Page