views:

1627

answers:

5

I am creating a custom .net hardware framework that will be used by other programmers to control some hardware. They will add a reference to our DLL to get to our hardware framework. I am in need of a shared class that will be accessed from multiple applications (processes).

The singleton pattern seems to be what I need but it only works for multiple threads inside your process. I could be completely wrong but here is an example of the C# code I currently have. I can't help to feel that the design is incorrect. I wish I could share more specific information but I can't.

  • I must stress that I will have no control over the customer application. The solution must be contained inside the framework (DLL) itself.

The Framework: (Shared DLL)

public class Resources
{
 static readonly Resources m_instance = new Resources();

 public string Data;

 private Resources()
 {
  Data = DateTime.Now.ToString();
 }

 public static Resources Instance
 {
  get
  {
   return m_instance;
  }
 }
}

The Test Application: (eventually customer app)

class Program
{
 static void Main(string[] args)
 {
  Console.WriteLine("Press enter to capture the resource!");
  Console.ReadLine();

  var resources = Resources.Instance;
  Console.WriteLine("\r\n{0}: {1}\r\n", Thread.CurrentThread.ManagedThreadId, resources.Data);

  BackgroundWorker worker = new BackgroundWorker();
  worker.DoWork += WorkerDoWork;
  worker.RunWorkerAsync();

  while (worker.IsBusy)
  {
   Thread.Sleep(100);
  }

  Console.WriteLine("Press enter to close the process!");
  Console.ReadLine();
 }

 static void WorkerDoWork(object sender, DoWorkEventArgs e)
 {
  var resources = Resources.Instance;
  Console.WriteLine("\r\n{0}: {1}\r\n", Thread.CurrentThread.ManagedThreadId, resources.Data);
 }
}

The first launched application gives an output of:

Press enter to capture the resource!

1: 6/24/2009 8:27:34 AM

3: 6/24/2009 8:27:34 AM

Press enter to close the process!

The second application gives an output of:

Press enter to capture the resource!

9: 6/24/2009 8:27:35 AM

10: 6/24/2009 8:27:35 AM

Press enter to close the process!

Conclusion:

I would like to see both applications return the same string of the time of the first instantiation of the class.

As you can see the singleton works for the multiple thread inside the process but not cross processes. Maybe this can't be done for I can't seem to find any solution.

+1  A: 

You cannot use a singleton to sync across applications. Each runs in its own application space, and as a matter of security cannot access memory/objects/etc. from the other without a method of communication (like remoting) To sync the two they would have to remote into a third program.

Kevin
+4  A: 

Yes it is possible to share a singleton amongst several processes. However you will need to take advantage of a technology which supports interprocess communication in order to achieve this result.

The most popular technologies which allow you to share out your object fairly directly are Remoting and WCF.

Giving an example of sharing a singleton with either of these is beyond the scope of an SO answer. But there are many tutorials on the web for each of these. Googling either technology plus singleton should put you on the right path.

JaredPar
+2  A: 

To add to the Kevin's answer, your constructor for your class Resources should really be made private for it to be a true singleton, otherwise nothing is stopping someone from creating a new instance of the Resources class through the constructor. This doesn't solve your problem, but it does stop one from misusing the Singleton.

AlbertoPL
You are correct about the constructor to be private. I fixed the sample.
Bobby Cannon
This is only an example. I'm not trying to share a date. I am trying to control a hardware resource.
Bobby Cannon
A file in that case will be no good. My mistake.
AlbertoPL
+1  A: 

Simply calling a singleton property in a different assembly from two different processes will create different instances of that class.

But you can easily share information between processes using .Net Remoting, or fire interprocess events if you only need simple signaling (EventWaitHandle).

[Edit:] To make it look like a Singleton to your callers, you can expose a class which will internally use Remoting to instantiate a singleton, and then return the instance transparently. Here is an example which (I think) does that: http://www.codeproject.com/KB/dotnet/remotingsingleton.aspx

Groo
A: 

There are ways to do it as mentioned above. But it is clumsy if you use WCF or remoting. Please try interprocess thread sync techniques.

For more info read the online free e-book on threading

http://www.albahari.com/threading/

Specially see the cross process sync constructs here ...

http://www.albahari.com/threading/part2.aspx#_Synchronization_Essentials

Shafqat Ahmed