Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make sure we have only one instance, and it is disposed in a correct way

In the software I am writing I will read some data from an external device (connected via USB). The drivers I have been given (dll file) are not thread safe and only one instance can be used at a time. I have to write a wrapper to these drivers in C#. Given that I have a multi-threaded application, I would like to make sure that:

  1. Always only one instance is used (probably the wrapper being a singleton?).
  2. It can be disposed of to release the drivers and resources there (IDisposable?).

From Disposable Singleton I can see that the opinions are divided, can a singleton be IDisposable or not. Maybe there is a better solution to both? Any help welcome.
For now I have an IDisposable singleton, like below:

using System;
using System.Runtime.InteropServices;

namespace Philips.Research.Myotrace.DataReading.Devices
{
    class MyDevice: IDisposable
    {
        private static volatile MyDeviceInstance;
        private static object SyncRoot = new Object();

        private bool disposed = false;

        private MyDevice()
        {
            //initialize unmanaged resources here (call LoadLibrary, Initialize, Start etc)
        }

        public MyDevice GetInstance()
        {
            if (Instance == null)
            {
                lock (SyncRoot)
                {
                    if (Instance == null)
                    {
                        Instance = new MyDevice();
                    }
                }
            }

            return Instance;
        }

        public void Dispose()
        {
            this.Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    //dispose of unmanaged resources here (call Stop and Close from reflection code

                    Instance = null;
                }

                this.disposed = true;
            }
        }

        [DllImport("devicedrivers.dll")]
        private static extern bool Initialize();
        [DllImport("devicedrivers.dll")]
        private static extern bool LoadLibrary();
        [DllImport("devicedrivers.dll")]
        private static extern bool Start();
        [DllImport("devicedrivers.dll")]
        private static extern bool Stop();
        [DllImport("devicedrivers.dll")]
        private static extern bool Close();
        //and few more
    }
}
like image 910
Daniel Gruszczyk Avatar asked Feb 27 '14 13:02

Daniel Gruszczyk


People also ask

When should you implement a dispose?

If you access unmanaged resources (e.g. files, database connections etc.) in a class, you should implement IDisposable and overwrite the Dispose method to allow you to control when the memory is freed.

What happens if Dispose is not called?

Implement a finalizer to free resources when Dispose is not called. By default, the garbage collector automatically calls an object's finalizer before reclaiming its memory.


1 Answers

The operating system is responsible for cleaning up unmanaged resources when the process terminates. So if you're happy for the resources to be allocated from the point at which you first use the resource until the program termination, I wouldn't implement IDisposable at all.

Having said that, for the sake of testability I would quite possibly avoid exposing the singleton publicly. Consider creating an interface and using dependency injection to inject the same instance throughout your code. I generally dislike singletons. If you're going to use one though, I'd suggest following one of the later patterns in my article on singletons. Avoid all this double-checked locking nonsense :)

like image 161
Jon Skeet Avatar answered Sep 27 '22 03:09

Jon Skeet