如何解决C#单例课程运行良好确认
我需要确认单例模式。
我有一个单例课程,并将其用作dll。我编写了一个对此dll进行引用的程序,并将其称为单例类。 我写了第二个程序,我也做同样的事情。
如果我告诉你,即使我有两个程序,他们也会同时调用我的singleton类的单个实例吗?
我尝试增加一个静态变量instancenumber,每次通过构造函数时,instancenumber都会增加,并且两个程序都告诉我instancenumber为1。所以应该没问题,但是我需要您的建议以确保确定。
谢谢。最好的问候
单例课程:
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; } }
}
}
程序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);
}
}
}
程序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);
}
}
}
解决方法
如果我告诉你,即使我有两个程序,他们也会同时调用我的singleton类的单个实例吗?
不。那不是它的工作原理。每个程序都在其内存空间中加载dll的副本,因此每个程序都有其自己的类实例。您可以将第一个程序启动5次,然后将第二个程序启动3次,届时您的班级将有8个实例。
他们没有被分享。
如果需要证明,只需进行证明,以便可以 write 到实例,例如 set 名称。您会看到,无论您在一个程序中做什么,其他程序都不会看到这些更改。
有多种方法可以在应用程序之间共享数据,共享dll中的类不是其中一种,因为每个程序都将加载它自己的dll副本。
,在程序中,代码永远不会重复,否则您会重复自己,但是在运行时不会重复:一种方法不会重复,并且拥有一个方法,总会有一个方法。该代码是相同的,并且永远不会更改,否则将使用例如代码保护或病毒所使用的一些高级技术。因此,一旦加载到内存中的 CODE SEGMENT 中,处理器和操作系统就只能控制一个正在运行的代码实例,并且直到最后都不会更改。
这是 DATA SEGMENT 中的数据,您可以使用它们,并且可以使用类型,局部变量,实例变量成员,静态成员和类,单例模式以及如此变化。
也就是说,每次可执行文件加载一个DLL时都会加载它的一个副本,因此,如果5个应用程序加载一个DLL,则内存中有5个DLL副本,因此这里有5个单例实例但是每个应用程序唯一。因此,在您启动的每个进程实例中都存在一个单例:每个应用程序有一个单例,每个加载的DLL一个。因此,您总是会看到1
的{{1}}:每个应用程序中有一个,但是1 + 1 + 1 + ... =很多,并且数据不会共享。
因此,如果在每个正在运行的应用程序中为InstanceNumber
设置了不同的值,则每个应用程序将同时具有自己的更改值,因为它们既不共享也不被复制。
如果要在多个进程之间共享全局系统单例,则需要使用某些 client-server 技术(例如 COM / DCOM)来实现服务器 在晚年。
要做到这一点,您不必使用由多个应用程序加载的DLL来将单例放入其中,但您必须有一个真实的应用程序(当然可以加载某些DLL,但是只有此服务器才能加载它们,并且单例代码可以放在DLL中,希望在此不会让您感到困惑),其他应用程序连接并要求使用提供的公共服务。
您可以使用Windows技术,命名管道,TCP /套接字,远程处理,WFC,Web服务等许多技术。
当我说数据库就像您要求的单例用法时,您将彻底了解:数据库是一个且只有一个实例(通常),并且客户端连接到该实例并使用,读取和写入,创建并更改和删除在多个本地和/或远程应用程序之间共享的相同数据位置。
例如,您当然有一个不好的示例来进行演示,它是故意完成的,SQLite可以用作每个客户端加载的DLL,但是此DLL管理单个数据库文件。因此请记住,您想要做的是管理相同的数据,而该DLL这样做是因为数据不在内存中,而仅在一个文件中。
因此,要解决您的问题,您需要:
-
创建单例代码。
-
选择适合您需求的服务器技术。
-
将单例放在可执行文件或仅由服务器可执行文件加载的dll中。
-
创建客户端代码。
-
运行单例应用程序。
-
运行一个或多个客户端。
某些技术允许客户端(如果尚未启动)直接启动服务器。
如果需要,必须通过使用Assembly GUID作为互斥量的名称来使服务器进程多次运行,以使其保持高度一致:
Restrict multiple instances of an application
How to Restrict the Application to Just One Instance
因此,您在Visual Studio解决方案资源管理器中将有两个项目。 Visual Studio提供了通过同时运行多个项目来调试它的方法:
https://docs.microsoft.com/visualstudio/ide/how-to-set-multiple-startup-projects
以下是一些文章:
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)
,在其他答案中提到了很多技术,建议您考虑找到最适合您需求的技术。本质上,所有答案都告诉您(正确)您不能仅通过共享dll来建立单例。
尚未提及其他三种方法(我假设您不只是需要在客户端之间共享应用程序名称,还希望共享更多数据-如果您更准确地告诉我们您的用例,我们可以为您提供帮助您最好为您的问题找到解决方案):
-
跨域单例(使用共享内存)。您可以找到详细信息here。
Simon Mourier在评论中也分享了一个很好的链接:单击here以关注它。 -
缓存。用于存储简单的数据结构。您可以使用Redis(https://redis.io/)之类的缓存在客户端之间共享数据。它安装简单,使用简单(您甚至可以在docker实例中运行它),并且使用键值集合存储共享数据。
-
设置数据库。然后,两个客户端都连接到数据库,然后将共享信息存储在该数据库中。甚至可以存储复杂的数据结构。
可在此处找到有关如何使用C#访问数据库的完整演练: https://www.guru99.com/c-sharp-access-database.html 此说明是针对SQL Server的,但是对于其他数据库(例如PostgresSQL,MySQL等),它的工作原理当然也是如此-如果您使用的是其他数据库系统,则需要特定的数据库库,您可以轻松地找到它们通过NUGET。
如果我告诉你,即使我有两个程序,我也可以吗? 都是我的单例课程的单个实例?
简短的回答:不,每个程序都有自己的实例。
但是,您在其中一篇评论中写道,您的目标是从PLC检索数据,并确保仅执行一次。这正是SCADA服务器所做的。我建议您了解一下什么是OPC服务器以及如何将其用于不同的数据传输(OLE,TCP等)。
在使用C#时,建议您看一下该库(https://github.com/OPCFoundation/UA-.NETStandard),该库是根据OPC Foundation标准使用.NET Framework的OPC UA堆栈实现。
,这有点令人困惑。您希望在两个不同程序之间使用Singleton作为DLL,但是每个程序在加载时将加载DLL的不同实例。因此,他们不会使用相同的Singleton。
在您的示例中,如果两个程序同时运行,那么一个运行秒应该返回2,因为第一个获得Singleton的程序会将变量增加到一个。
,如其他答案所示,两个程序之间不共享单例实例。每个程序都在具有自己的DLL副本的自己的OS进程中运行
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。