2014-05-07 8 views
6

Więc mam następujący kod:C# mutex w trybie zwolnienia zachowuje się inaczej niż w trybie debugowania

... 
private static void Main(string[] args) 
{ 
    string file=DateTime.Now.ToFileTime().ToString(); 
    File.AppendAllText(file, "Mutex\r\n"); 

    bool CreatedNew; 
    Mutex mutex=new Mutex(true, AppDomain.CurrentDomain.FriendlyName, out CreatedNew); 

    if(CreatedNew) 
    { 
     #if DEBUG 
     File.AppendAllText(file, "Launching in DEBUG mode\r\n"); 
     #else 
     File.AppendAllText(file, "Launching in RELEASE mode\r\n"); 
     #endif 

     //Program.Launch(); 
     Program.ProcessArgsAndLaunch(args); 
    } 
    else 
    { 
     File.AppendAllText(file, "Handling dupe\r\n"); 
     Program.HandleDuplicate(); 
    } 
} 
... 

Sprawdziłem niezliczone artykuły tutaj i innych miejsc bez powodzenia.

Zasadniczo kod sprawdza działającą instancję aplikacji, a jeśli takowa istnieje, przechodzi do głównego okna uruchomionej aplikacji. Jeśli nie, uruchamia aplikację.

W trybie Debug wszystko działa zgodnie z oczekiwaniami, problem rozpoczyna się po zmianie konfiguracji na Release: aplikacja zawsze się uruchamia (z Mutex pozornie nie robi nic).

Dodałem warunkowo skompilowane zrzuty, które pokazują, w którym trybie aplikacja się uruchamia, a wyniki zmieniają się w zależności od konfiguracji, ale niestety tak samo postępuje aplikacja.

To może być race condition, ale nie jestem pewien.

Więcej kodu zostanie wysłany w razie potrzeby.

Dzięki.

Odpowiedz

11

Wraz z odpowiedzią Juana, istnieje różnica w zakresie zbierania śmieci między uruchomienie wewnątrz i na zewnątrz debuggera. To nie tak jak konfiguracja debugowania w stosunku do konfiguracji wydania, ale jest to coś, o czym powinieneś wiedzieć.

W debugger, zmienna lokalna będzie działać jako korzeń GC dla całego zakresu jej stosowania - ale jeśli nie jesteś debugowanie, zmienna mutex nie jest pierwiastkiem GC w ogóle, bo NIE użytkowania po jej inicjalizacji. Oznacza to, że Twój Mutex może zostać wyrzucony do śmieci (a zatem natywny muteks zostanie zwolniony) niemal natychmiast.

Należy użyć using oświadczenie wyraźnie wyrzucać Mutex we właściwym czasie:

// Note that you don't need a variable here... you can have one if you 
// want though 
using (new Mutex(...)) 
{ 
    // Code here to be executed while holding the mutex 
} 
+0

Wielkie dzięki Jon, to był problem. Jak tylko umieściłem swój kod w instrukcji 'using', wszystko działało. I masz rację, nie potrzebowałem zmiennej ... – nurchi

8

Jeśli masz jedną instancję działającą jako debugowanie i inną jako Release, nie będą one miały tego samego muteksu, ponieważ AppDomain.CurrentDomain.FriendlyName różni się w zależności od tego, czy proces hostingu jest aktywny, czy też nie.

Jak widać tutaj: http://msdn.microsoft.com/en-us/library/ms242202.aspx

+0

Przepraszam, jeśli to było jasne, chciałbym skompilować pod 'Debug' lub' Release', a następnie uruchomić nowo skompilowana aplikacja z "Explorera". Następnie chciałbym zamknąć (wszystkie) instancje, wyczyścić rozwiązanie, zmienić konfigurację, a następnie ponownie skompilować, a następnie uruchomić (ponownie, z 'Windows Explorer') ... – nurchi