Может ли класс Singleton внутри DLL быть общим для процессов? - PullRequest
12 голосов
/ 24 июня 2009

Я создаю пользовательскую среду .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: 24.06.2009 8:27:34

3: 24.06.2009 8:27:34

Нажмите ввод, чтобы закрыть процесс!

Второе приложение выдает:

Нажмите ввод, чтобы захватить ресурс!

9: 24.06.2009 8:27:35

10: 24.06.2009 8:27:35

Нажмите ввод, чтобы закрыть процесс!

Заключение

Мне бы хотелось, чтобы оба приложения возвращали одну и ту же строку времени первого создания класса.

Как видите, синглтон работает для нескольких потоков внутри процесса, но не для перекрестных процессов. Может быть, этого нельзя сделать, потому что я не могу найти никакого решения.

Ответы [ 5 ]

7 голосов
/ 24 июня 2009

Да, можно разделить синглтон между несколькими процессами. Однако вам нужно будет воспользоваться технологией, которая поддерживает межпроцессное взаимодействие для достижения этого результата.

Самыми популярными технологиями, которые позволяют вам напрямую делиться своим объектом, являются Remoting и WCF.

Дать пример совместного использования синглтона с любым из них выходит за рамки SO-ответа. Но в Интернете есть много учебных пособий для каждого из них. Google или технология плюс синглтон должны поставить вас на правильный путь.

3 голосов
/ 24 июня 2009

Вы не можете использовать одноэлементную синхронизацию между приложениями. Каждый работает в своем собственном прикладном пространстве и в целях безопасности не может получить доступ к памяти / объектам / и т. Д. от другого без метода связи (например, удаленного взаимодействия) Чтобы синхронизировать два, они должны были бы удалить в третью программу.

2 голосов
/ 24 июня 2009

Чтобы добавить ответ Кевина, ваш конструктор для вашего класса Resources действительно должен быть закрытым, чтобы он был настоящим синглтоном, иначе ничто не мешает кому-то создать новый экземпляр класса Resources через конструктор. Это не решит вашу проблему, но остановит злоупотребление Singleton.

1 голос
/ 24 июня 2009

Простой вызов одноэлементного свойства в другой сборке из двух разных процессов создаст разные экземпляры этого класса.

Но вы можете легко обмениваться информацией между процессами, используя .Net Remoting или запускать межпроцессные события, если вам нужна только простая сигнализация ( EventWaitHandle ).

[Edit:] Чтобы ваши звонки выглядели как Singleton, вы можете предоставить класс, который будет использовать Remoting внутри для создания экземпляра singleton, а затем прозрачно вернуть экземпляр. Вот пример, который (я думаю) делает это: http://www.codeproject.com/KB/dotnet/remotingsingleton.aspx

0 голосов
/ 24 июня 2009

Есть способы сделать это, как указано выше. Но это неуклюже, если вы используете WCF или удаленное взаимодействие. Пожалуйста, попробуйте методы синхронизации потоков между процессами.

Для получения дополнительной информации читайте онлайн бесплатную электронную книгу по теме

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

Специально см. Конструкции перекрестной синхронизации здесь ...

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

...