![]() |
Mutex zwischen 2 Prozessen
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Community,
was möchte ich erreichen?: Die Anwendung soll pro Datenbank-Verbindung nur einmalig geöffnet werden können. meine Lösungsidee: Durch das Verwenden von "Mutex" mit Bezeichner (Anwendungsname + Verbindungsinfo) wird überprüft, ob das Programm mit dieser DB-Verbindung bereits läuft. mein Problem: Das Mutex verhalten zwischen Prozessen ist sehr merkwürdig. Ich starte meine Testanwendung (siehe code unten bzw. Anhang) 2 mal. locken in 1. Anwendung locken in 2. Anwendung schlägt fehl unlocken in 1. Anwendung locken in 1. Anwendung schlägt fehl Habt ihr eine Idee?
Delphi-Quellcode:
//prozedur zum locken
procedure TForm1.btn1Click(Sender: TObject); var LMutex: THandle; begin LMutex := CreateMutex(nil, True, pCHAR('test')); if (LMutex = 0) or (GetLastError <> 0) then begin MessageDlg(SysErrorMessage(GetLastError), mtInformation, [mbOk], 0); end else FMutex := LMutex; end; //prozedur zum unlocken procedure TForm1.btn2Click(Sender: TObject); begin ReleaseMutex(FMutex); CloseHandle(FMutex); end; |
AW: Mutex zwischen 2 Prozessen
CreateMutex erzeugt immer ein neues Handle, wenn die Rechte ausreichen.
Das heißt, wenn du den btn1 drückst, bekommst du jedesmal ein neues Handle, das aber nicht mehr freigegeben wird. Somit hilft es nicht, wenn du btn2 drückst, da das "neue" Handle nicht freigegeben wird. Es sollte genügen, wenn in btn1 prüfst, ob dein FMutex-Handle bereits existiert und dann gar nicht erst durch die Prozedur läufst. |
AW: Mutex zwischen 2 Prozessen
Das habe ich schon dadurch abefangen, dass FMutex nur gesetzt wird, wenn es keinen Fehler beim erzeugen gab.
Der besagte Fehler tritt auf, wenn das Mutex in unterschiedlichen Anwendungs-Instanzen erstellt wird. |
AW: Mutex zwischen 2 Prozessen
Zitat:
Delphi-Quellcode:
Erzeugt immer ein neues Handle.
LMutex := CreateMutex(nil, True, pCHAR('test'));
Du kannst dsas mit dem Debugger auch leicht prüfen. Oder, wenn du den Source so änderst, wirst du sehen, dass es das Handle gibt:
Delphi-Quellcode:
LMutex := CreateMutex(nil, True, pCHAR('test'));
if (LMutex = 0) or (GetLastError <> 0) then begin MessageDlg(SysErrorMessage(GetLastError), mtInformation, [mbOk], 0); // Durch diesen Code, wird das fehlerhafte Handle wieder freigegeben: if LMutex <> 0 then begin ReleaseMutex(LMutex); CloseHandle(LMutex); end; end else FMutex := LMutex; |
AW: Mutex zwischen 2 Prozessen
Natürlich könnte ich ein bestehendes Mutex freigeben, das ist aber nicht meine Absicht.
Ich möchte das Mutex nutzen um zu Prüfen ob das Programm bereits gestartet ist. Wenn ich das Mutex einfach freigebe wiederspräche es seinem Sinn Kannst du bitte versuchen mein Problem einmal nachzuvollziehen? Zitat:
|
AW: Mutex zwischen 2 Prozessen
Zitat:
wenn das Mutex bereits existiert, wird das Handle des bestehenden Mutex zurückgeliefert |
AW: Mutex zwischen 2 Prozessen
Zitat:
Due erzeugst in deiner Prozedur ein neues LOKALES Handle auf das Mutex. Und zwar jedesmal ein weiteres, wenn du den Button drückst. Beim ersten mal weißt du LMutex dem FMutex zu. Alle weiteren CreateMutex werden von dir nicht wieder freigegeben. Und genau das verursacht das von dir beschriebene Problem.
Code:
Bitte benutze den Debugger und schaue dir an, was das CreateMutex zurückgibt. Es ist ein neues Handle. Zumindest ist das bei mir so.
Es wird doch kein neues Handle erzeugt, wenn ein Fehler auftritt..
wenn das Mutex bereits existiert, wird das Handle des bestehenden Mutex zurückgeliefert |
AW: Mutex zwischen 2 Prozessen
Zitat:
Zitat:
1 Mutex - mehrere Handles zu diesem Mutex. Interessant ist in diesem Fall wahrscheinlich, dass GetLastError ERROR_ALREADY_EXISTS zurückgibt, falls das Mutex schon existiert hat und kein neues erstellt wurde. |
AW: Mutex zwischen 2 Prozessen
Hier etwas funktionierendes zum Spielen
Delphi-Quellcode:
unit Unit1;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.SyncObjs, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TForm1 = class( TForm ) Button1: TButton; Button2: TButton; procedure Button1_Click( Sender: TObject ); procedure Button2_Click( Sender: TObject ); private FMutex: TMutex; public procedure AfterConstruction; override; procedure BeforeDestruction; override; end; var Form1: TForm1; implementation {$R *.dfm} const Mutex_Name = {$IFDEF GLOBAL}'global\'+{$ENDIF}'MyMutex'; procedure TForm1.AfterConstruction; begin inherited; FMutex := TMutex.Create( nil, false, Mutex_Name ); end; procedure TForm1.BeforeDestruction; begin FMutex.Free; inherited; end; procedure TForm1.Button1_Click( Sender: TObject ); begin if FMutex.WaitFor( 0 ) = TWaitResult.wrSignaled then begin // We have the mutex Button1.Enabled := false; Button2.Enabled := True; end; end; procedure TForm1.Button2_Click( Sender: TObject ); begin // We have the mutex, so we release it FMutex.Release; Button1.Enabled := True; Button2.Enabled := false; end; end. |
AW: Mutex zwischen 2 Prozessen
@Michael:
Ja, du hast Recht. Es ist ein neues Handle auf das selbe Mutex. Dennoch muss das Handle wieder freigegeben werden. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz