C# DLL中的单例类能否跨进程共享?

C# DLL中的单例类能否跨进程共享?,c#,dll,frameworks,singleton,shared-libraries,C#,Dll,Frameworks,Singleton,Shared Libraries,我正在创建一个自定义的.net硬件框架,其他程序员将使用它来控制一些硬件。他们将添加对我们的DLL的引用,以访问我们的硬件框架。我需要一个可以从多个应用程序(进程)访问的共享类 单例模式似乎是我所需要的,但它只适用于进程内的多个线程。我可能完全错了,但下面是我目前使用的C代码的一个例子。我忍不住觉得这个设计不正确。我希望我能分享更具体的信息,但我不能 我必须强调,我将无法控制客户应用程序。解决方案必须包含在框架(DLL)本身中 框架:(共享DLL) 测试应用程序:(最终为客户应用程序) 第一

我正在创建一个自定义的.net硬件框架,其他程序员将使用它来控制一些硬件。他们将添加对我们的DLL的引用,以访问我们的硬件框架。我需要一个可以从多个应用程序(进程)访问的共享类

单例模式似乎是我所需要的,但它只适用于进程内的多个线程。我可能完全错了,但下面是我目前使用的C代码的一个例子。我忍不住觉得这个设计不正确。我希望我能分享更具体的信息,但我不能


  • 我必须强调,我将无法控制客户应用程序。解决方案必须包含在框架(DLL)本身中
框架:(共享DLL)

测试应用程序:(最终为客户应用程序)

第一个启动的应用程序提供以下输出:

按enter键捕获资源

1:6/24/2009上午8:27:34

3:6/24/2009上午8:27:34

按enter键关闭进程

第二个应用程序的输出为:

按enter键捕获资源

9:6/24/2009上午8:27:35

10:6/24/2009上午8:27:35

按enter键关闭进程

结论

我希望看到两个应用程序都返回类第一次实例化时的相同字符串


正如您所看到的,单线程适用于进程内的多线程,但不适用于跨进程。也许这无法做到,因为我似乎找不到任何解决方案。

您不能使用单例在应用程序之间进行同步。每一个都在其自己的应用程序空间中运行,并且出于安全考虑,如果没有通信方法(如远程处理)来同步这两个,则无法从另一个访问内存/对象/等。它们必须远程连接到第三个程序。

是的,可以在多个进程之间共享一个单例。但是,您需要利用支持进程间通信的技术来实现此结果

允许您相当直接地共享对象的最流行的技术是远程处理和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);
    }
}