C#单例课程运行良好确认

如何解决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);
    }
}
}

Result of programs

解决方法

如果我告诉你,即使我有两个程序,他们也会同时调用我的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来建立单例。

尚未提及其他三种方法(我假设您不只是需要在客户端之间共享应用程序名称,还希望共享更多数据-如果您更准确地告诉我们您的用例,我们可以为您提供帮助您最好为您的问题找到解决方案):

  1. 跨域单例(使用共享内存)。您可以找到详细信息here
    Simon Mourier在评论中也分享了一个很好的链接:单击here以关注它。

  2. 缓存。用于存储简单的数据结构。您可以使用Redis(https://redis.io/)之类的缓存在客户端之间共享数据。它安装简单,使用简单(您甚至可以在docker实例中运行它),并且使用键值集合存储共享数据。

  3. 设置数据库。然后,两个客户端都连接到数据库,然后将共享信息存储在该数据库中。甚至可以存储复杂的数据结构。
    可在此处找到有关如何使用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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-