Создание экземпляров мьютексов между процессами - PullRequest
2 голосов
/ 06 мая 2020

Просто написал простую программу, которую нужно обрабатывать один раз, поэтому для этого нужно использовать ключ Mutex с определенным именем.
Код (упрощенный) выглядит так.

static readonly string APP_NAME = "MutexSample";

static void Main(string[] args)
{
    Mutex mutex;
    try
    {
        mutex = Mutex.OpenExisting(APP_NAME);
        // At this point, with no exception,
        // the Mutex is acquired, so there is another
        // process running
        // Environment.Exit(1); or something
    }
    catch (WaitHandleCannotBeOpenedException)
    {
        // If we could not acquire any mutex with
        // our app name, let's create one
        mutex = new Mutex(true, APP_NAME);
    }

    Console.ReadKey(); // Just for keeping the application up
    // At some point, I just want to release
    // the mutex
    mutex.ReleaseMutex();
}

Моя первая попытка заключалась в создании экземпляра Mutex как new Mutex(false, APP_NAME), но при вызове mutex.ReleaseMutex() генерировалось исключение

System.ApplicationException: 'Object synchronization method was called from an unsynchronized block of code.'

Только что заметил, что первый параметр конструктора (initiallyOwned) отмечает, владеет ли им текущий поток, создающий Mutex, и, что неудивительно, поток не может освободить Mutex, который не принадлежит этому потоку.

Таким образом, изменение этого параметра на true устранило эту проблему, как показано в приведенном выше коде.

Ну, у меня вопрос, в чем весь смысл этого параметра? Я имею в виду, когда мне нужно будет создать Mutex, которое я не могу выпустить.
И, если я установлю для параметра initiallyOwned значение false, кто действительно владеет этим Mutex?

Спасибо.

Ответы [ 2 ]

1 голос
/ 06 мая 2020

Никто не владеет Mutex, если он не приобретен кем-то, вызвав его метод WaitOne. Передача initiallyOwned: true - это попытка немедленно получить вновь созданный Mutex, но это проблематично c. Из документации :

Вы не должны использовать этот конструктор для запроса первоначального владения, если вы не уверены, что поток создаст именованный мьютекс.

Существует также перегрузка , которая принимает три параметра:

public Mutex (bool initiallyOwned, string name, out bool createdNew);

... но проще просто создать Mutex без первоначального владения , а затем приобретите его, когда будете готовы к блокировке (в случае, если он будет приобретен кем-то другим).

mutex = new Mutex(initiallyOwned: false, APP_NAME);
mutex.WaitOne(); // Potentially blocking
1 голос
/ 06 мая 2020

когда мне нужно будет создать Mutex, который я не могу выпустить.

Это действительно слишком общий вопрос. Но менее широкий вопрос:

Как я могу выпустить Mutex, который изначально не принадлежал мне, когда я его создавал?

И ответ на это это просто: просто приобретите Mutex после того, как вы его создадите. Затем вы можете выпустить его.

И, если я установил для параметра initiallyOwned значение false, кому на самом деле принадлежит этот мьютекс?

Это зависит от того, Mutex уже был создан и получен другим потоком или процессом. Если бы это было не так, то никто им не владеет, и ваш код сможет получить его позже.

Конечно, для сценария, с которым вы имеете дело, вы этого не сделаете. обязательно даже хочу обзавестись Mutex. Обычный подход - попытаться создать Mutex с помощью этого конструктора . Третий параметр будет установлен, если ваш код действительно создал Mutex. Вам никогда не нужно его приобретать; вы просто используете тот факт, что ОС гарантирует, что Mutex будет создан только один раз.

Обратите внимание, что уже есть много действительно хороших советов по написанию программ с одним экземпляром с. NET. Я настоятельно рекомендую вам ознакомиться с информацией, найденной здесь: Как правильно создать приложение WPF с одним экземпляром? Как ограничить программу одним экземпляром

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