tags:

views:

254

answers:

6

I have a Singleton class that manages the connection to an external device. The idea of my application is that I need that external device to be presented all the time when the application is alive.

The Singleton has the following functionalities:

  1. Initialization, look for the device at the application startup time
  2. communicate with the external device, note that this can spread over multiple assemblies at multiple points.
  3. Close the connection when the application exits.

For the last part, I am thinking about putting the code inside Dispose method of the singleton class, to guarantee that the resource is always cleanup upon closing. But since I am using a Singleton, and since singleton life span will only be terminated when the application exits, there is no need to explicitly close the connection in Dispose since the connection will be close anyway.

So, the question is, should I put the close connection code inside Dispose method?

+1  A: 

IDisposable != Destructor like C++, it has to be called explictly.

Anyway, having a Disposable Singleton does not make much sense, IMO. What if some code actually did Dispose off your Singleton? What happens if some other code tries to access that singleton now? You probably should not put the connection close there for that reason.

In fact, you should not even have the Singleton implement IDisposable in the first place.

A better option might be to have the Singleton hook onto one of the .NET exit events. Perhaps use Application.ApplicationExit (or Application.Exit) event, or something similar.

Moron
Using `Application.Exit` makes me implement the same line of code in all of my application, which I really hate. I want to not concern about the closing connection part at all, if possible
Ngu Soon Hui
.NEt will raise some event on exit. Make your singleton class hook onto that, and close the connection there. Check MSDN. http://msdn.microsoft.com/en-us/library/system.windows.application.exit.aspx might be a good starting point.
Moron
@Ngu: If you want to cleanly close the connection, you have to write that code anyway. The main question is _where_.
Moron
+4  A: 

Implementing IDisposable alone doesn't mean Dispose will be called on exit.

Not enough details to understand your application but if closing incorrectly leaves the device in a bad state than maybe a try/finally or as Moron suggested Application.Exit (depending on the application of course).

Even then you're not guaranteed that code executes so maybe I'm not clear as to what you are trying to accomplish or what problem you are trying to solve.

Edit:

Per the OPs comment the best option (for his desire to have "cleanup" code execute without being specifically called and untestable) would be to put it in the deconstructor/finalizer. Note this is not guaranteed to run but should run in most circumstances without being called (unlike Dispose):

public class Foo
{
    public Foo()
    {
        //Constructor
    }

    ~Foo()
    {
        // Deconstructor/finalizer
    }
}
Cory Charlton
@cory, I am trying to make sure that when the app exits the connection will be closed, no matter what.
Ngu Soon Hui
@Ngu Soon Hui: That's the part I don't understand. When the application exits (no matter how) the communication is closed. So are you trying to prevent the device from being in a bad state? Or something else?
Cory Charlton
@Cory, I am trying to prevent manually that the communication is closed when application exits.
Ngu Soon Hui
@Cory, sorry, `prevent==make sure`
Ngu Soon Hui
There is no guaranteed way to make sure (consider abnormal application exits ie: power failure) but the finalizer will be called w/o you calling it. Unlike dispose.
Cory Charlton
A: 

Do both, as in have an explicit Close() or Shutdown() method and also call that in the dispose (track if called etc, see dispose pattern help...)

That way you can implement the IDisposable interface (which makes the intention obvious) and call it in your code.

Are you using a "finally" block around the startup code?

internal static class App
{
    [STAThread]
    private static void Main(string[] args)
    {
        try
        {
            Thing.Startup();
            Application.Run();
        }
        finally
        {
            Thing.Shutdown(); // or dispose
        }
    }
}

Get my drift?!

PK :-)

PS: A "singleton" should be written as a normal class, the singleton part should be an external use thing

Paul Kohler
+1 for separating lifetime management from other functionality! You could use a Plain Old CLR Object with an IoC Container framework to handle the lifetime management.
TrueWill
I resisted getting into using container for management (e.g. castle windsor)..:-)
Paul Kohler
The last part `Thing.Shutdown();` is something I want to avoid to write in `main` body
Ngu Soon Hui
@ngu soon hui - agreed, its just to get the dispose point across. I try to do as much as possible in pure class code form, makes for cleaner testable code etc.
Paul Kohler
A: 

As others have said, Dispose will not be automatically called on exit, however a finalizer method will be called. I would do that instead to do your cleanup logic on application exit.

Kevin Stafford
Under normal circumstances, yes. Abnormal, no. That's what I don't get. What problem is he trying to prevent with his question and can he resolve it on next load/usage?
Cory Charlton
Finalizers are not guaranteed to be called even in normal scenarios. Did I miss some new .NET development?
Moron
Nothing is guaranteed and that is my main point. I think he's just asking for something that he doesn't have to specifically call/execute. Which is what the deconstructor/finalizer provides.
Cory Charlton
@Cory: Yes, nothing is guaranteed. You/Kevin probably guessed the right intention, though, inspite of the title (IDisposable in Singleton good practice?) of the question.
Moron
depending on finalizers is a really bad idea since you never know when or even IF they'll run.
No Refunds No Returns
+1  A: 

This is bad design. You would be better served having Open and Close methods that you call at the appropriate time. It will be easier to test, debug and support.

No Refunds No Returns
But having to manually called Open and Close is cumbersome.
Ngu Soon Hui
yeah ... I've *always* found verifiable, testable code cumbersome. But I don't worry about that cuz *I sleep all night*.
No Refunds No Returns
A: 

Instead of the finalizer or try...catch I would suggest to use the using stement.

Microsoft explains: "The using statement ensures that Dispose is called even if an exception occurs[...]" This sounds to me like what you are looking for: Close the connection in any case when the application closes.

Although it is internally translated into a try...finally statement, this is the recommended way to ensure that the Dispose() method is called. After leaving the using block the object gets disposed and goes out of scope.

internal static class App
{
    [STAThread]
    private static void Main(string[] args)
    {
        using (YourSingeletonClass thing = YourSingeletonClass.GetInstance()) 
        {
            thing.Startup();
            Application.Run();
        }
    }
}

MSDN documentation for using statement can be found here: http://msdn.microsoft.com/en-us/library/yh598w02.aspx

Sensei76
yeah .. and if you multiple singletons you can just nest those using statements. *not*
No Refunds No Returns