Какое из приведенных ниже выражений Mutex идеально предотвращает множественные экземпляры приложения .Net и в чем разница? - PullRequest
9 голосов
/ 24 августа 2011

Обычно я вижу эти две части кода повсюду.И то, и другое работает в моем случае, но к чему я должен придерживаться?

Случай 1:

bool isNew = false;
Mutex mutex = new Mutex(true, "MyApp_Mutex", out isNew);
if (!isNew)
{
    MessageBox.Show("already running.", "Multiple Instances Not Allowed",
                                        MessageBoxButtons.OK, 
                                        MessageBoxIcon.Exclamation);
    return;
}

Случай 2:

Mutex mutex = new Mutex(false, "MyApp_Mutex"))            
if (!mutex.WaitOne(0, false))
{
    MessageBox.Show("already running.", "Multiple Instances Not Allowed", 
                                        MessageBoxButtons.OK, 
                                        MessageBoxIcon.Exclamation);
    return;
}
  1. Какой идеальный путь между двумя для предотвращения множественных случаев?

  2. В чем разница?

  3. Более того, я вижу такие коды:

    //if not return{
    mutex.ReleaseMutex(); 
    GC.Collect(); 
    //application.Run();
    GC.KeepAlive(mutex); 
    

по второму способу, но никогда по первому.Почему это так?Или я ошибся?

В основном это связано с правильным пониманием используемых параметров и методов.Буду признателен, если кто-нибудь сможет вкратце рассказать об этом, я понимаю не половину при чтении документации MSDN.

Ответы [ 2 ]

8 голосов
/ 24 августа 2011

В первом случае вы просите ОС создать мьютекс и дать вам право собственности на него, если он создан - это делается с помощью первого параметра, initiallyOwned.Параметр isNew сообщает вам, был ли это новый мьютекс.Если он новый, то вы гарантированно обладаете им, так как вы просили это с параметром initiallyOwned.Поскольку оно новое, и вы им владеете, вы знаете, что нет других экземпляров запущенного приложения, потому что если бы оно было, они бы уже создали мьютекс и им бы владели.

Второй случай в основномто же самое, но сделано немного по-другому.Он не запрашивает владение при создании, а при вызове WaitOne.WaitOne запрашивает владение и ожидает 0 миллисекунд.Если вы получаете право собственности, то вы знаете, что другой экземпляр вашего приложения не работает по тем же причинам, что и в случае 1.

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

Добавление ответа на новый вопрос # 3

Когда приложение будет завершено, оно должно освободить мьютекс, так как оновладеет этим..NET, вероятно, выпустит его для вас, когда закроется ваше приложение, но это хорошая практика.GC.Collect и GC.KeepAlive имеют дело со сборкой мусора.Я не могу придумать ни одного сценария, почему эти вызовы понадобятся при работе с мьютексами, управляющими запуском.Я объявляю свой мьютекс как статический, так что он всегда будет находиться в области видимости и не будет освобожден сборщиком мусора в течение всего времени жизни моего приложения.

3 голосов
/ 24 августа 2011

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

Объявление Mutex в вашем первом фрагменте кода использует isNew bool, чтобы указать, что текущий экземпляр приложения был запущен первым, а также первый экземпляр, создавший Mutex. Это означает, что каждое вторичное выполнение вашего приложения может быть проинформировано о том, что его дескриптор общесистемного Mutex не был первым, кто создал и получил доступ к Mutex.

Следующий блок if затем проверяет, было ли ассоциированное задание первым подать сигнал Mutex, а затем соответствующим образом обрабатывает состояние.

Второй фрагмент кода совершенно другой. Mutex может использоваться в задаче (задача B) для ожидания другой задачи (задача A), чтобы подать сигнал Mutex о том, что любая другая задача (задача B) может быть продолжена.

Метод WaitOne(secs, releaseConext) говорит: подождите, пока Mutex отправит ответный сигнал в течение X секунд , если он заблокирован другим потоком . Если метод не получает ответный сигнал через X секунд, он возвращает false и, в случае вашего примера кода, входит в блок if, который используется для закрытия приложения.

Лично я бы использовал первый фрагмент кода. Я полагаю, что они оба работают с одинаковым количеством накладных расходов. Тем не менее, при выборе какой версии использовать, я бы посчитал, что первый метод является наилучшим для использования на практике.

...