【问题标题】:Can a Singleton Class inside a DLL be shared across processes?DLL 中的单例类可以跨进程共享吗?
【发布时间】:2010-11-05 12:06:14
【问题描述】:

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

单例模式似乎是我所需要的,但它只适用于进程中的多个线程。我可能完全错了,但这是我目前拥有的 C# 代码示例。我不禁觉得设计不正确。我希望我可以分享更具体的信息,但我不能。

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

框架:(共享 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);
    }
}

第一个启动的应用程序会输出:

按回车键获取资源!

1:2009 年 6 月 24 日上午 8:27:34

3:2009 年 6 月 24 日上午 8:27:34

按回车键关闭进程!

第二个应用程序给出以下输出:

按回车键获取资源!

9: 2009 年 6 月 24 日上午 8:27:35

10: 2009 年 6 月 24 日上午 8:27:35

按回车键关闭进程!

结论

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

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

【问题讨论】:

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

标签: c# dll frameworks singleton shared-libraries


【解决方案1】:

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

允许您直接共享对象的最流行的技术是 Remoting 和 WCF。

举一个与其中任何一个共享单例的示例超出了 SO 答案的范围。但是对于这些中的每一个,网上都有很多教程。谷歌搜索任何一种技术加上单例应该会让你走上正确的道路。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我也有同样的问题,但作为替代方案,我可以不将此单例实例放在 GAC 中,并且两个进程都可以引用该实例吗?这样,如果我从一个进程更新对象,另一个进程不会获得更新的实例吗?还是每个进程都在自己的进程中加载​​实例?
    • @hangar18 这是完全相同的问题 - 将它放在 GAC 中并没有什么特别之处,它仍然是一个 dll!
    【解决方案3】:

    添加到 Kevin 的答案中,您的类 Resources 的构造函数应该真正私有化,以使其成为真正的单例,否则没有什么能阻止某人通过构造函数创建 Resources 类的新实例。这并不能解决您的问题,但确实可以防止滥用 Singleton。

    【讨论】:

    • 你是正确的关于构造函数是私有的。我修复了样本。
    • 这只是一个例子。我不想分享约会。我正在尝试控制硬件资源。
    【解决方案4】:

    只需从两个不同的进程调用不同程序集中的单例属性将创建该类的不同实例。

    但是您可以使用 .Net Remoting 在进程之间轻松共享信息,或者如果您只需要简单的信号 (EventWaitHandle),则可以触发进程间事件。

    [编辑:] 为了让调用者看起来像单例,您可以公开一个类,该类将在内部使用远程处理来实例化单例,然后透明地返回实例。这是一个(我认为)这样做的例子:http://www.codeproject.com/KB/dotnet/remotingsingleton.aspx

    【讨论】:

      【解决方案5】:

      如上所述,有很多方法可以做到这一点。但是如果你使用 WCF 或远程处理就很笨拙。请尝试进程间线程同步技术。

      有关更多信息,请阅读有关线程的在线免费电子书

      http://www.albahari.com/threading/

      这里专门查看跨进程同步构造...

      http://www.albahari.com/threading/part2.aspx#_Synchronization_Essentials

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-26
        • 2018-10-27
        • 2012-07-06
        • 2012-10-31
        相关资源
        最近更新 更多