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:
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
}
}
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 :)
I would not recommend having a directly-disposable static singleton, but rather have a method which returns an IDisposable
object (or list of objects) encapsulating the currently-connected device(s). A lot of USB drivers which are mostly limited to single-threaded operation have a single situation where multi-threading is allowed: any thread may request that a driver instance shut down, causing any pending or future operations to abort at first opportunity. The shutdown may not be immediate, and if one wants to shut down and restart a device which has gotten "stuck" one must be prepared for the possibility that re-open attempts may fail and/or block if issued before the shutdown is complete.
Although the OS will try to clean up any USB device drivers a program may be using when it exits, such cleanup doesn't always work, and I would avoid relying upon it. It would be better to dispose of things you can, when you know they're no longer needed. From an abstraction standpoint, if one uses a singleton method which will identify the connected device(s), if any, there's no problem with disposing the device(s) identified thereby. Once devices are disposed, they'll no longer appear on the list until something is done to re-establish connection.
链接地址: http://www.djcxy.com/p/19292.html