2009-05-11 19 views
1

Ich habe zwei Instanzen des gleichen Windows-Dienstes ausgeführt. Sie überprüfen die Gesundheit der anderen und berichten, wenn ein Problem gefunden wird. Ich habe einen kritischen Job, der ausgeführt werden muss, damit ich ihn mit einem Failover-Ansatz ausführen kann, er läuft im Master und wenn der Master nicht antwortet, läuft er im Slave. Dieser Job muss über eine bestimmte serielle Schnittstelle kommunizieren. Ich versuche, Mutex zu verwenden, um den Race-Zustand zu überprüfen. Ich habe keinen Zugriff auf die Produktion, also möchte ich vor der Bereitstellung sicherstellen, dass mein Ansatz in Ordnung ist. Bitte schlage also vor, ob meine Verwendung von Mutex für den gegebenen Fall in Ordnung ist.Benutzt Mutex

if (iAmRunningInSlave) 
{ 
    HealthClient hc = new HealthClient(); 
    if (!hc.CheckHealthOfMaster()) 
     return this.runJobWrapper(withMutex, iAmRunningInSlave); 
    else 
     return true; //master is ok, we dont need to run the job in slave 
} 
return this.runJobWrapper(withMutex, iAmRunningInSlave); 

Und dann in runJobWrapper

bool runJobWrapper(bool withMutex, bool iAmRunningInSlave) 
{ 
    if (!withMutex) 
     return this.runJob(iAmRunningInSlave); //the job might be interested to know 
    Mutex mutex = null; 
    string mutexName = this.jobCategory + "-" + this.jobTitle; //this will be unique for given job 
    try 
    { 
     mutex = Mutex.OpenExisting(mutexName); 
     return false; //mutex is with peer, return false which will re-trigger slave 
    } 
    catch 
    { 
     try 
     { //mean time mutex might have created, so wrapping in try/catch 
     mutex = new Mutex(true /*initiallyOwned*/, mutexName); 
     return this.runJob(iAmRunningInSlave); //the job might be interested to know where I am running 
     } 
     finally 
     { 
     if (null!=mutex) mutex.ReleaseMutex(); 
     } 
     return false; 
    } 
} 

Antwort

3

hatte ich ein ähnliches Problem vor kurzem.

Das Design der Mutex Klasse ist ein bisschen seltsam/anders als die normalen Klassen in .NET.

Mit OpenMutex auf eine vorhandene Mutex zu überprüfen ist nicht wirklich nett, da Sie eine Ausnahme fangen müssen.

Ein besserer Ansatz ist es, die

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

Konstruktor zu verwenden, und überprüfen Sie die von createdNew zurückgegebene Wert.

+0

Es ist TryOpenExisting Methode aufzurufen. –

+0

Es erschien in .NET 4.5. –

0

Sie suchen nicht, um den Rückgabewert von runJobWrapper überall zu überprüfen - ist das absichtlich? Es ist nicht offensichtlich, was der Rückgabewert tatsächlich bedeutet. Auch sollten Sie wirklich nicht jede Ausnahme fangen, die OpenExisiting möglicherweise werfen könnte - nicht genügend Speicher? Paketüberfluss? usw. etc. Fangen Sie einfach die, die Sie richtig handhaben wollen.

Auch Ihr Code sieht etwas fragil aus - ich wäre nicht überrascht, wenn Sie Race Conditions haben.

+0

der erste Teil wurde von Hand geschrieben Scaled Down-Variante ... ich habe es verpasst ... hat die Frage bearbeitet –

0

Ich bemerkte, dass mutex.ReleaseMutex() den Mutex nicht wurde die Freigabe immediately..I hatte GC.Collect()

+1

Vorsichtig über Ihre Erwartungen ist der .NET GC nicht deterministisch – annakata

+1

mutex.ReleaseMutex() ist nicht Dispose()! Es gibt die vom Mutex gehaltenen Ressourcen nicht frei, aber es "entriegelt" den Mutex, so dass andere Prozesse ihn über Mutex.WaitOne() akquirieren können. Verwenden Sie mutex.Close(), um den Mutex zu entsorgen. Bitte lesen Sie die Dokumentation. – Emiswelt