C# DLL中的单例类能否跨进程共享?
我正在创建一个自定义的.net硬件框架,其他程序员将使用它来控制一些硬件。他们将添加对我们的DLL的引用,以访问我们的硬件框架。我需要一个可以从多个应用程序(进程)访问的共享类 单例模式似乎是我所需要的,但它只适用于进程内的多个线程。我可能完全错了,但下面是我目前使用的C代码的一个例子。我忍不住觉得这个设计不正确。我希望我能分享更具体的信息,但我不能C# DLL中的单例类能否跨进程共享?,c#,dll,frameworks,singleton,shared-libraries,C#,Dll,Frameworks,Singleton,Shared Libraries,我正在创建一个自定义的.net硬件框架,其他程序员将使用它来控制一些硬件。他们将添加对我们的DLL的引用,以访问我们的硬件框架。我需要一个可以从多个应用程序(进程)访问的共享类 单例模式似乎是我所需要的,但它只适用于进程内的多个线程。我可能完全错了,但下面是我目前使用的C代码的一个例子。我忍不住觉得这个设计不正确。我希望我能分享更具体的信息,但我不能 我必须强调,我将无法控制客户应用程序。解决方案必须包含在框架(DLL)本身中 框架:(共享DLL) 测试应用程序:(最终为客户应用程序) 第一
- 我必须强调,我将无法控制客户应用程序。解决方案必须包含在框架(DLL)本身中
正如您所看到的,单线程适用于进程内的多线程,但不适用于跨进程。也许这无法做到,因为我似乎找不到任何解决方案。您不能使用单例在应用程序之间进行同步。每一个都在其自己的应用程序空间中运行,并且出于安全考虑,如果没有通信方法(如远程处理)来同步这两个,则无法从另一个访问内存/对象/等。它们必须远程连接到第三个程序。是的,可以在多个进程之间共享一个单例。但是,您需要利用支持进程间通信的技术来实现此结果 允许您相当直接地共享对象的最流行的技术是远程处理和WCF
给出一个与其中任何一个共享单例的示例超出了SO答案的范围。但是网上有很多关于这些的教程。谷歌搜索任何一种技术加上singleton都会让你走上正确的道路 为了补充Kevin的答案,类资源的构造函数应该真正私有化,使其成为真正的单例,否则没有什么可以阻止某人通过构造函数创建资源类的新实例。这并不能解决您的问题,但它确实可以防止误用Singleton。简单地从两个不同的进程调用不同程序集中的Singleton属性将创建该类的不同实例 但是,您可以使用.Net在进程之间轻松共享信息,如果您只需要简单的信令()就可以触发进程间事件
[编辑:要使它在调用者看来像一个单例,您可以公开一个类,该类将在内部使用远程处理实例化一个单例,然后透明地返回实例。这里有一个例子(我认为)可以做到这一点:如上所述,有很多方法可以做到这一点。但如果使用WCF或远程处理,则会很笨拙。请尝试进程间线程同步技术 有关更多信息,请阅读关于线程的在线免费电子书 这里特别介绍跨进程同步构造
您认为构造函数是私有的,这是正确的。我修正了样本。这只是一个例子。我不想和你约会。我试图控制硬件资源。我必须强调,我将无法控制客户应用程序。解决方案必须包含在框架(DLL)本身中。我有同样的问题,但作为替代方案,我可以不将此单例实例放在GAC中,并且两个进程都可以引用该实例吗?这样,如果我从一个进程更新对象,那么另一个进程不会得到更新的实例吗?还是每个进程都在自己的进程中加载实例?@hangar18这是完全相同的问题-将它放在GAC中没有什么特别的作用,它仍然是一个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;
}
}
}
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);
}
}