Mutex handling

Thomasio

Erfahrenes Mitglied
Ich habe 2 Anwendungen, die das selbe File lesen und schreiben sollen, und damit das nicht gleichzeitig passieren kann, möchte ich den Zugriff in einen Mutex einpacken.
Die Erklärung bei MSDN sieht ganz einfach aus, aber irgendwas mache ich trotzdem falsch.

Ich trau mich gar nicht erst Code zu posten, ich habe 100 Varianten probiert, inzwischen weiss ich gar nicht mehr wo mir der Kopf steht.
Ich will doch nur:

CreateMutex()
Datei Zugriff
ReleaseMutex()

Dazwischen gehört irgendwie ein loop der via GetLastError() solange wartet, bis Erfolg, aber dieser Loop hängt bei mir immer die ganze Anwendung auf, offensichtlich weil der Mutex nicht richtig gelöscht wird.
Ich vermute, dass mein Problem bei "Mutex löschen" liegt, denn ReleaseMutex löscht ihn ja nicht, sondern gibt ihn nur frei.

Kann mir jemand auf die Sprünge helfen?
 
Ganz einfach :)
Zum Beispiel so:

C++:
HANDLE hMutex = CreateMutex(NULL, // wir brauchen anfangs keinen Security descriptor
                            FALSE,           // das Mutex gehört anfangs nicht gleich uns
                            "MeinMutex");    // irgend ein mutex name, der möglichst eindeutig (unique) sein sollte.. 

if (!hMutex)
{
          // Mutex erstellen fehlgeschlagen...
          // sollte hofftl nie passieren..
}

if (GetLastError() == ERROR_ALREADY_EXISTS)
{
   // ein anderer Prozess hat das Mutex schon erstellt,
   // ist aber kein Problem, wir können das Handle trotzdem benutzen
   // ist interessant, falls du Single-Instance-Programme haben willst
}


// jetzt kannst du mit dem Mutex arbeiten:


if (WaitForSingleObject(hMutex, 20) != WAIT_TIMEOUT)
{
  // jetzt gehört das Mutex uns
  // wir arbeiten an der Ressource
  // und nach getaner Arbeit geben wir das Mutex wieder frei,
  // damit ein anderer Prozess/Thread es ergattern kann
  ReleaseMutex(hMutex);
}


// wenn du beliebig lange auf ein Mutex warten willst, weil du für den weiteren
// Programmablauf brauchst:

WaitForSingleObject(hMutex, INFINITE);

// .. code

ReleaseMutex(hMutex);



// wenn du das mutex gar nicht mehr brauchst:

CloseHandle(hMutex);

Gut wäre, du postest vielleicht doch einmal, was du für Code geschrieben hast, damit man dir helfen kann.
 
Zuletzt bearbeitet:
Erstmal danke für die Antwort.

Wie gesagt, ich hatte 100 Varianten probiert, auch diese, zumindest so ähnlich.
Nur hatte ich statt WaitForSingleObject() in GetLastError einen loop drin, der warten sollte, bis der Mutex nicht mehr existiert, was (inzwischen klar) dazu führt, dass er nie aus dem loop raus kommt, weil ReleaseMutex() ihn nicht löscht, sondern nur frei gibt.

Was mir an deinem Code nicht ganz klar ist:

1) Wieso kann ich GetLastError() einfach überspringen und trotzdem mit dem Mutex arbeiten? Ich dachte der Error ist mein Anhaltspunkt, dass ich eben nicht weiter machen kann, sondern warten muss.
2) Wieso gehört nach WaitForSingleObject() der Mutex mir?
 
1) Wieso kann ich GetLastError() einfach überspringen und trotzdem mit dem Mutex arbeiten? Ich dachte der Error ist mein Anhaltspunkt, dass ich eben nicht weiter machen kann, sondern warten muss.

Du darfst tatsächliche Fehler nicht übergehen (Rückgabewert von CreateMutex == NULL)

Sollte das Mutex bereits existieren, ist das jedoch noch kein Fehler. Dir wird ein gültiges Handle auf das Mutex zurückgegeben (solange du die Access-Rights bekommst).
Mit diesem Handle kannst du arbeiten.
Wenn du ein gültiges Handle und nicht NULL zurück geliefert bekommst, kannst du mit GetLastError überprüfen, ob das Mutex bereits vor deinem Funktionsaufruf existierte oder ob du es erst erstellt hast.
Das ist nicht immer wichtig, du brauchst es also eventuell gar nicht.
Es ist hauptsächlich interessant, wenn du erkennen willst, ob schon eine Instanz deines Programmes läuft und dann zum Beispiel die Kommandozeile an diese Instanz übergeben willst...

msdn hat gesagt.:
If the mutex is a named mutex and the object existed before this function call, the return value is a handle to the existing object, GetLastError returns ERROR_ALREADY_EXISTS, bInitialOwner is ignored, and the calling thread is not granted ownership. However, if the caller has limited access rights, the function will fail with ERROR_ACCESS_DENIED and the caller should use the OpenMutex function.


2) Wieso gehört nach WaitForSingleObject() der Mutex mir?

"Dir gehören" ist symbolisch zu verstehen.
Ein Mutex hat sozusagen immer maximal einen Besitzerthread.
Das ist der, der als letztes erfolgreich WaitForSingleObject (oder eine der anderen Wait-Funktionen) auf das Mutex ausgeführt hat.
Der Besitzerthread kann mit ReleaseMutex() das Mutex freigeben, so dass ein anderer Besitzer werden kann.
Man kann also ein Mutex wie einen Zugriffsschutz auf irgend eine Ressource verwenden, auf die nur ein Thread gleichzeitig zugreifen darf.
Man vereinbart einfach die Konvention, dass ein Thread das Mutex besitzen muss, um auf die Ressource zuzugreifen.
 
Zurück