4

I have class instantiated in a web service that, in a static member, holds on to some resources. If I was not statically holding on to these resources, I'd probably access them through some IDisposable object where I could release the resources on Dispose. Regardless of whether or not holding on to this session is a good idea, does .NET provide any way to call any clean up code when a type is statically deconstructed?

PLEASE DO NOT ANSWER THIS QUESTION WITH ANYTHING LIKE "STOP HOLDING RESOURCES IN A STATIC MEMBER VARIABLE". I understand the drawbacks to holding on to this information statically and am willing to accept the consequences (we're using it to cut processing time from 58 hours to 4 hours for some batch processing that we do). The question specifically is: given this situation, is there anyway for me to nicely clean up those resources?

EDIT: I understand that the class will live for the rest of the process, but with static constructors .NET gives you the opportunity to do something when that type is loaded into memory. Can you do anything on the opposite end?

LJM
  • 6,284
  • 7
  • 28
  • 30
  • 10
    When would a static type be deconstructed? – haiyyu Feb 07 '12 at 19:16
  • @haiyyu - that's a very good question, I have no idea. – LJM Feb 07 '12 at 19:17
  • 3
    It sounds like you *don't* really understand the drawbacks of using static variables like this, given that one of the drawbacks is "their lifetime is the lifetime of the AppDomain"... I would investigate whether you could tie this into part of the web service life cycle and still avoid the static member. – Jon Skeet Feb 07 '12 at 19:22
  • @JonSkeet - I understand that static means they live for the lifetime of the app domain. But still, when you load the type into memory, you get this feature of a static constructor. When the AppDomain dies, does everything just go away and no clean up code can be run? I feel like my confusion is regarding what happens when the AppDomain dies. – LJM Feb 07 '12 at 19:29
  • @LJM: You can hook into `AppDomain.DomainUnload`, but I would strongly suggest that you don't. – Jon Skeet Feb 07 '12 at 19:29
  • Well, flattery aside, if Jon Skeet says not to do it, I'm not going to do it. I was more just curious how it would happen. Thank you. – LJM Feb 07 '12 at 19:33

5 Answers5

3

The question does not really make sense, static lives for the lifetime of the process, when a process ends then everything is cleaned up by the OS. A process cannot continue to use resources if it is not running any longer.

Ben Robinson
  • 21,601
  • 5
  • 62
  • 79
  • I was trying to generalize the question too much. In this specific situation, we have a session open with some services else where. It'd be nice to be able to close out that session. – LJM Feb 07 '12 at 19:18
  • 2
    I think you need to ask a more specific question with details of your app. For example asp.net has an `application_end` method that allows you to do this type of thing when the process ends or is restarted. But the answer would be different for windows service. – Ben Robinson Feb 07 '12 at 19:21
3

There actually is no way to do it from managed code. What you want is to handle your assembly being unloaded, but that doesn't happen under most circumstances when you want it to.

In more detail:

There is an AppDomain.DomainUnload event ( http://msdn.microsoft.com/en-us/library/system.appdomain.domainunload.aspx ) you can handle. This handles when your application domain gets unloaded from its hosting process (say ASP.NET).

However, if you are an EXE, or the hosting EXE is being recycled, this will not be raised. If you set up correctly, you might be able to handle the native DLL_PROCESS_DETACH and bounce that back to managed code, but because of the loader lock you will have to be very careful what you do from that context (anything that triggers an assembly load will deadlock).

You can read this for some insight on what cleanup is requited (hint: not much): http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx

Basically, the only thing you need to worry about is flushing buffers to disk, and if you need to do anything more complex, you have already screwed up. malloc(), and therefore new() could crash your program instantly. This applies to managed code as well.

Joshua
  • 40,822
  • 8
  • 72
  • 132
2

When is the last point this static state is going to be important? At this moment, you should destruct it.

Destruct might mean something like "release some unmanaged memory, write out a cache to the database and set the static variable to null".

The last point of access will mean different things in different applications. In an ASP.NET application, you cannot reliably determine this point. It comes when the Application_End event or the AppDomain.Unload events fire, whichever comes first. The same in WCF. In a WinForms app you would to it after the main form has closed or as the last line of the main application.

In any case you need to do the cleanup yourself.

Alternative: You can encapsulate your state into a finalizable object. It will be cleaned up on AppDomain unload. If you write a so called critical finalizer you are pretty much guaranteed that your cleanup will execute.

usr
  • 168,620
  • 35
  • 240
  • 369
1

You cannot destruct something that hasn't been instantiated.

I think you should use Singleton pattern instead of holding all data statically.

Peter Kiss
  • 9,309
  • 2
  • 23
  • 38
  • By that logic you could say that you cannot "construct" something that is static, but that'd be untrue. We have static constructors. – LJM Feb 07 '12 at 19:32
  • Let's say we have a class names Foo with a static constructor. When it's static constructor is calling we aren't instantiating any Foo object in that constructor. Static constructors only initializating the class not an object from that class. – Peter Kiss Feb 07 '12 at 20:28
-1

If the objects you are storing as static members properly implement IDisposable, then the .net runtime should take care of any resources when the app unloads. If any of the objects do not do this, then I suggest you create wrapper classes that implement IDisposable so that you can clean up after yourself.

IDisposable on MSDN

Ray
  • 21,485
  • 5
  • 48
  • 64
  • Do you have anything I can reference to confirm this? I want to understand better how it works. – LJM Feb 07 '12 at 19:43
  • I don't know of any reference that talks about your exact situation, other than the IDisposable docs in msdn (which explains it pretty well - link added to answer). If you create a wrapper class, you could attach your debugger, and then unload the process and see what happens. You should be able to set a breakpoint in your Dispose method, or else write to a log or something to prove it got called. – Ray Feb 07 '12 at 20:02