Reputation: 153
I need a confirmation about a singleton pattern.
I've a singleton class and I'm using it as dll. I write a program with a reference to this dll and I call my singleton class. I write a second program and I do the same.
Am I right if I tell you that even if I have two program they call both a single instance of my singleton class?
I tried to increment an static variable instancenumber that increment each time I pass the constructor and both programs tell me that the instancenumber is 1. So it should be ok but I need your advice to be sure.
Thank you. best regards
Class Singleton:
namespace SingletonClassLib
{
public class SingletonClass
{
public static int InstanceNumber = 0;
private static string myName;
#region //Singleton initialisation
private SingletonClass() { createInstance(); }
private void createInstance()
{
InstanceNumber++;
myName = myName + InstanceNumber.ToString();
}
public static SingletonClass _I { get { return NTCSession._i; } }
private class NTCSession
{
static NTCSession() { }
internal static readonly SingletonClass _i = new SingletonClass();
}
private static List<WeakReference> instances = new List<WeakReference>();
#endregion //Singleton initialisation
public static string askname { get { return myName; } }
}
}
Program 1:
using System.Windows.Forms;
using SingletonClassLib;
namespace Singletontest
{
public partial class Form1 : Form
{
SingletonClass myclass = SingletonClass._I;
public Form1()
{
InitializeComponent();
string Name = SingletonClass.askname;
MessageBox.Show("Program first: "+Name);
}
}
}
Program 2:
using System.Windows.Forms;
using SingletonClassLib;
namespace Singletontest
{
public partial class Form1 : Form
{
SingletonClass myclass = SingletonClass._I;
public Form1()
{
InitializeComponent();
string Name = SingletonClass.askname;
MessageBox.Show("Program second: "+Name);
}
}
}
Upvotes: 5
Views: 883
Reputation:
In a program the code is never repeated, otherwise what you repeat yourself, but there is no duplication at runtime: a method is not duplicated, and having one method, there is always one method. The code is the same and never change, else using some advanced technics used by code protection or viruses for example. So the processor and the operating system master only one instance of the running code once loaded in the memory, in the CODE SEGMENT, and it is never changed until the end.
This is the data in the DATA SEGMENT with what you work and that you manage in different ways of allocations using types, local variables, instance variables members, static members and classes, singleton pattern, and so on, that change.
That said, each time an executable load a DLL it loads a copy of it, so if 5 applications loads one DLL, there is 5 copies of the DLL in the memory, so here there is 5 instances of the singletons that is however unique per application. Therefore, the singleton here exists in each instance of processes you start: you have one singleton per application, one per loaded DLL. Hence you always see 1
for InstanceNumber
: one in each application, but 1 + 1 + 1 + ... = many and the data is not shared.
Thus, if you set myName
with differents values in each running application, each application has its own changed value at the same time because it is not shared nor replicated.
If you want to have a global system singleton shared between several processes, you need to implement a server using some client-server technologies like COM/DCOM in the old age.
To do that you don't use a DLL loaded by several applications to put the singleton in it, but you must have a real application (that can load some DLL of course but only this server loads them and the singleton code can be putted in a DLL and I hope saying that will not confuse you here), where others application connect and ask to use the public services provided.
You can use many technics like Windows Service, Named Pipes, TCP/Sockets, Remoting, WFC, Web Services, and so on.
You will definitivally understand when I would have said that a database is like the singleton usage you ask for: the database is one and only one instance (in general), and clients connect to it and use, read and write, create and change and delete the same data location shared between several applications local and /or remote.
Of course you have for example, a bad exemple here for the demonstration and it's done on purpose, SQLite that can be used as a DLL loaded by each clients, but this DLL manage a single database file. So keep in mind that what you want to do is to manage the same data, and this DLL do that because the data is not in memory but in only one file.
Thus, to solve your problem you need to:
Create the singleton code.
Choose a server technic adapted to your needs.
Put the singleton in an executable or in a dll only loaded by the server executable.
Create the client code.
Run the singleton application.
Run the client or the clients.
Some technics allow the client to directly start the server if not already starded.
If needed you must disallow running the server process multiple times by using the Assembly GUID as the name of the mutex to be strongly consistent:
Restrict multiple instances of an application
How to Restrict the Application to Just One Instance
Hence you will have two projects in your Visual Studio solution explorer. Visual Studio offers ways to debug that by running multiple projects at the same time:
https://learn.microsoft.com/visualstudio/ide/how-to-set-multiple-startup-projects
Here are some articles:
Create A Windows Service In C# (C-SharpCorner)
Develop and Install a Windows Service in C# (C-SharpCorner)
WCF Comparison with Web Services and .NET Remoting (CodeProject)
Inter Process Communication (C# Vault)
Full Duplex Asynchronous Read/Write with Named Pipes (CodeProject)
Socket Programming In C# (C-SharpCorner)
Socket Programming in C# (GeeksForGeeks)
Simple Client-server Interactions using C# (CodeProject)
Upvotes: 4
Reputation: 61
Am I right if I tell you that even if I have two program they call both a single instance of my singleton class?
Short answer: no, each program will have its own instance.
However, in one of the comments you wrote that your goal is to retrieve data from a PLC and being sure that is done only once. This is exactly what a SCADA server does. I suggest you to take a look to what an OPC server is and how it can be used with different data transportation (OLE, TCP etc.).
As you are using C#, I suggest you to take a look to this library (https://github.com/OPCFoundation/UA-.NETStandard) which is a OPC UA stack implementation using .NET Framework according to OPC Foundation standard.
Upvotes: 1
Reputation: 1173
As other answers suggest, the singleton instance is not shared between the two programs. Each program runs in its own OS process that has its own DLL copy
Upvotes: 0
Reputation: 27001
There are a lot of techniques mentioned in the other answers, which I suggest you to consider to find the one that matches best your needs. In essence, all answers told you (correctly) that you cannot establish a singleton by just sharing a dll.
Three additional approaches were not yet mentioned (I am assuming that you don't just need to share the application name between the clients, you want to share more data - if you tell us your use case more precisely, we can help you better to find a solution for your question):
Cross-domain singleton (using shared memory). You can find details here.
Simon Mourier has also shared a good link in the comments: Click here to follow it.
Caching. Useful to store simple data structure. You can use a cache like Redis (https://redis.io/) to share data between your clients. It is simple to install, simple to use (you can even run it in a docker instance) and it uses a key-value collection to store shared data.
Set up a database. Then both clients connect to the database, and you store the shared information there. Even complex data structures can be stored.
A complete walkthrough how to access a database in C# can be found here:
https://www.guru99.com/c-sharp-access-database.html
This description is for SQL Server, but of course it is working similar for other databases (such as PostgresSQL, MySQL, ...) - if you're using a different database system, you need specific database libraries, which you can easily find via NUGET.
Upvotes: 1
Reputation: 77304
Am I right if I tell you that even if I have two program they call both a single instance of my singleton class?
No. That is not how it works. Each of your programs loads a copy of the dll in their memory space and so each of your programs has it's own instance of the class. You can start your first program 5 times and your second program 3 times and there will be 8 instances of your class.
They do not get shared.
If you need proof, just make it so that you can write to the instance, for example set the name. You will see that no matter what you do in one program, the others won't be seeing those changes.
There are different ways to share data between applications, a class in a shared dll is not one of them, because each program loads it's own copy of the dll.
Upvotes: 9
Reputation: 84
This is a little confusing. You want to use a Singleton between two different programs as a DLL, but each program when loaded will load a different instance of the DLL. So, they wouldn't be using the same Singleton.
In your example if the two programs where run at the same time then the one run second should return 2 since the first program to get the Singleton would of incremented the variable to one.
Upvotes: 0