2011-08-24 7 views
9

Zazwyczaj widzę te dwa fragmenty kodu dookoła. Oba działają również w moim przypadku, ale do których należy się trzymać?Które z poniższych wyrażeń Mutex idealnie zapobiega wielu wystąpieniom aplikacji .Net i jaka jest różnica?

Przypadek 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; 
} 

Przypadek 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. Który jest idealnym sposobem między nimi, aby zapobiec wielu wystąpień?

  2. Jaka jest różnica?

  3. Ponadto widzę kody takie jak:

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

ramach drugiej metody, ale nigdy z pierwszym. Dlaczego to jest takie? Czy też popełniłem błąd?

Zasadniczo leży to w prawidłowym rozumieniu użytych parametrów i metod. Byłbym wdzięczny, gdyby ktoś mógł to krótko uszczegółowić, rozumiem, że nie połowę, gdy czytam dokumentację msdn.

Odpowiedz

8

W pierwszym przypadku, prosisz system operacyjny o utworzenie muteksu i nadanie mu prawa własności, jeśli został utworzony - to odbywa się za pomocą pierwszego parametru, initiallyOwned. Parametr isNew informuje, czy był to nowy muteks. Jeśli jest nowy, masz gwarancję posiadania go, ponieważ o to prosiłeś z parametrem initiallyOwned. Ponieważ jest nowy i posiadasz go, wiesz, że nie ma innych wystąpień aplikacji, ponieważ gdyby tak było, to już stworzyliby muteks i byliby jego właścicielami.

Drugi przypadek to w zasadzie to samo, ale wykonane w nieco inny sposób. Nie żąda własności w kreacji, ale w rozmowie WaitOne. WaitOne prosi o prawa własności i czeka na 0 milisekund. Jeśli otrzymasz prawo własności, wiesz, że nie działa żadne inne wystąpienie Twojej aplikacji z tych samych powodów, co w przypadku 1.

Jeśli chodzi o wykorzystanie, według mojej wiedzy nie ma to znaczenia. Pierwszy wydaje się bardziej intuicyjny, przynajmniej dla mnie.

Dodawanie odpowiedzi na nowe pytania nr 3

Gdy aplikacja jest kompletna należy zwolnić mutex ponieważ jest jej właścicielem. .NET najprawdopodobniej wyda je za Ciebie, gdy Twoja aplikacja się zakończy, ale dobrą praktyką jest to zrobić. GC.Collect i GC.KeepAlive zajmują się usuwaniem śmieci. Nie mogę wymyślić żadnego scenariusza, dlaczego te wywołania byłyby potrzebne podczas pracy z muteksami sterującymi uruchamianiem. Deklaruję mój muteks jako statyczny, więc zawsze będzie on w zasięgu i nie zostanie zwolniony przez odśmiecacz na cały okres mojej aplikacji.

+0

Dzięki. Uważam, że pierwszy jest bardziej elegancki .. – nawfal

+0

Mam jeszcze jedną wątpliwość, którą dodam do pytania. Będzie to bardzo pomocne, jeśli będziesz mógł się temu przyjrzeć. – nawfal

+0

Tak, brzmi dla mnie logicznie. – nawfal

3

Aby zrozumieć, co dzieje się w tych wypowiedziach, trzeba zrozumieć, czym jest muteks i jak działają. Nie będę wchodził w szczegóły, ale wskażę ci to reference book. Przeczytaj kilka pierwszych rozdziałów, aż dojdziesz do sekcji o Muteksach.

Deklaracja Mutexa w twoim pierwszym fragmencie kodu używa boola isNew do określenia, że ​​bieżąca instancja aplikacji była uruchomiona jako pierwsza, jak również pierwsza instancja do utworzenia Mutex. Oznacza to, że każde wtórne wykonanie aplikacji może zostać poinformowane, że ich obsługa dla całego systemu Mutex nie był pierwszym, który utworzył i uzyskał dostęp do Mutex.

Następujący blok if następnie sprawdza, czy skojarzone zadanie było pierwszym, które zasygnalizowało Mutex, a następnie odpowiednio obsłuży stan.

Drugi fragment kodu jest zupełnie inny. Mutex może być użyty w zadaniu (zadanie B) do oczekiwania na kolejne zadanie (zadanie A), aby zasygnalizować Mutexowi, że inne zadanie (zadanie B) może być kontynuowane.

Sposób WaitOne(secs, releaseConext) mówi, czekać na mutex wysłać odpowiedź sygnału dla X sekund jeśli jest on zablokowany przez inny wątek. Jeśli metoda nie uzyska odpowiedzi sygnału w X sekundach, zwraca false i, w przypadku twojego kodu przykładowego, wchodzi w blok if, który jest używany do zamykania aplikacji.

Osobiście użyłbym pierwszego fragmentu kodu. Mogę sobie wyobrazić, że obie działają z taką samą ilością kosztów ogólnych. Jednak przy wyborze wersji, którą chciałbym zastosować, uznałbym pierwszą metodę za najlepszą do zastosowania jako ogólną praktykę.

+0

świetne wyjaśnienie! – nawfal

+0

Mam jeszcze jedną wątpliwość, którą dodam do pytania – nawfal

+0

Niestety, nie dostałem odpowiedzi na twoje zaktualizowane, dodatkowe pytanie (nr 3) przed C.C.G. odpowiedział. Przybił odpowiedź w głowę. Tak, dodatkowy kod jest uważany za "dobrą praktykę", ale GC został dobrze zoptymalizowany w ciągu ostatnich 10 lat i nigdy nie znalazłem potrzeby posiadania takiego kodu. +1 do CCG. – RLH

Powiązane problemy