External libraries / Threading / Critical sections
-
I am writing a class that wraps and helps me deal with calls to an external c++ library from C#. My class is used in a webservice environment, so must be sensitive to the multi-threaded nature of web requests, however I dont think the c++ library was ever written with this in mind so I must be careful how I call it. To simpify things the C++ library has a few methods I must call Init - must be called only once, the first time my class is used SendData - used to start a communication ReceiveEvent - must be called on a timer with a short interval, used for receiving events back from the external library (and I use it to raise events in my class) ShutDown - must be called once before the application exits Now this structure I think lends itself to a Singleton which takes care of the Init/Shutdown, and a factory method to create my instance of a "Call". Feel free to suggest another approach if you think im wrong there. The problem im having is in ensuring that "Init" has been called before any other thread manages to call SendData. eg Thread1 calls SingletonObject.Instance.CreateCall() - this starts the processof calling "Init" Thread2 calls SingletonObject.Instance.CreateCall() - however as Init has not yet completed this fails I have tried all sorts of variations of lock() and Mutex, but im not seeing the behaviour I expect. Here is some cut-down code which will hopefully demonstrate what im attempting (Methods prefixxed "X25" are the external calls). Any help appreciated as always.
public class Xot
{
#region Static
static Xot()
{
}
private static readonly Xot instance = new Xot();public static Xot Instance { get { return instance; } } #endregion private Dictionary<int,> calls; private bool initialised = false; private Timer waitTimer; private Xot() { calls = new Dictionary<int,>(); waitTimer = new Timer(this.ReadEvents, null, Timeout.Infinite, Timeout.Infinite); // Initialise the library, no other thread should be able to call //Instance.CreateCall until this has completed Console.WriteLine("Initialising Xot"); if (!this.initialised) { **lock (Xot.Instance) // this doesnt seem to do it nor does lock(this)** { int rc = X25.HsX25DllInit( "10.80.105.102", 0, 1024, 2,
-
I am writing a class that wraps and helps me deal with calls to an external c++ library from C#. My class is used in a webservice environment, so must be sensitive to the multi-threaded nature of web requests, however I dont think the c++ library was ever written with this in mind so I must be careful how I call it. To simpify things the C++ library has a few methods I must call Init - must be called only once, the first time my class is used SendData - used to start a communication ReceiveEvent - must be called on a timer with a short interval, used for receiving events back from the external library (and I use it to raise events in my class) ShutDown - must be called once before the application exits Now this structure I think lends itself to a Singleton which takes care of the Init/Shutdown, and a factory method to create my instance of a "Call". Feel free to suggest another approach if you think im wrong there. The problem im having is in ensuring that "Init" has been called before any other thread manages to call SendData. eg Thread1 calls SingletonObject.Instance.CreateCall() - this starts the processof calling "Init" Thread2 calls SingletonObject.Instance.CreateCall() - however as Init has not yet completed this fails I have tried all sorts of variations of lock() and Mutex, but im not seeing the behaviour I expect. Here is some cut-down code which will hopefully demonstrate what im attempting (Methods prefixxed "X25" are the external calls). Any help appreciated as always.
public class Xot
{
#region Static
static Xot()
{
}
private static readonly Xot instance = new Xot();public static Xot Instance { get { return instance; } } #endregion private Dictionary<int,> calls; private bool initialised = false; private Timer waitTimer; private Xot() { calls = new Dictionary<int,>(); waitTimer = new Timer(this.ReadEvents, null, Timeout.Infinite, Timeout.Infinite); // Initialise the library, no other thread should be able to call //Instance.CreateCall until this has completed Console.WriteLine("Initialising Xot"); if (!this.initialised) { **lock (Xot.Instance) // this doesnt seem to do it nor does lock(this)** { int rc = X25.HsX25DllInit( "10.80.105.102", 0, 1024, 2,
Just a couple of comments: 1) Your lock and if statement are backwards. 2 threads could get past the if statement. One would pass the lock and do the init, the other would hang at the lock. When the first exited the lock, the second would then be released and pass the lock and do the init again. 2) I wouldn't lock on the instance. Mainly because it's public (advised against). If you must use a lock, create a private lock object instead. 3) I wouldn't put the shut down code in a finaliser. Finalisers aren't guaranteed to be run, and if a finaliser blocks or throws an exception it can screw up your garbage collector thread - You definitely shouldn't be throwing exceptions from a finaliser, it will kill the garbage collector, and the exception will never get reported. I'd do it with a dispose pattern (and put the code inside the if block so it's only called when disposing and not when finalising) and make sure you call dispose manually from your applications shutdown routines. 4) It's a singleton. That means the constructor only gets called once. You've used a thread safe singleton patten, so unless I've missed something I think you don't need the initialised flag or the lock at all. Just ditch the lock and flag entirely and trust the singleton pattern to only create the object and call the constructor once.
Simon