AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Mutex zwischen 2 Prozessen

Ein Thema von TimWu · begonnen am 2. Nov 2018 · letzter Beitrag vom 2. Nov 2018
Antwort Antwort
Seite 1 von 2  1 2   
TimWu

Registriert seit: 27. Okt 2016
15 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#1

Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 11:27
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;
Angehängte Dateien
Dateityp: zip Projekte.zip (3,54 MB, 2x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.013 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 11:45
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.
Peter
  Mit Zitat antworten Zitat
TimWu

Registriert seit: 27. Okt 2016
15 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#3

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 12:08
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.
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.013 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 12:13
Das habe ich schon dadurch abefangen, dass FMutex nur gesetzt wird, wenn es keinen Fehler beim erzeugen gab.
Nein.
LMutex := CreateMutex(nil, True, pCHAR('test')); Erzeugt immer ein neues Handle.
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;
Peter
  Mit Zitat antworten Zitat
TimWu

Registriert seit: 27. Okt 2016
15 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#5

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 12:23
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:
locken in 1. Anwendung
locken in 2. Anwendung schlägt fehl
unlocken in 1. Anwendung
locken in 1. Anwendung schlägt fehl
  Mit Zitat antworten Zitat
TimWu

Registriert seit: 27. Okt 2016
15 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#6

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 12:25
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.
Es wird doch kein neues Handle erzeugt, wenn ein Fehler auftritt..
wenn das Mutex bereits existiert, wird das Handle des bestehenden Mutex zurückgeliefert
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.013 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#7

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 12:31
Kannst du bitte versuchen mein Problem einmal nachzuvollziehen?
Kannst du bitte versuchen zu verstehen, was ich schreibe?

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:
Es wird doch kein neues Handle erzeugt, wenn ein Fehler auftritt..
wenn das Mutex bereits existiert, wird das Handle des bestehenden Mutex zurückgeliefert
Bitte benutze den Debugger und schaue dir an, was das CreateMutex zurückgibt. Es ist ein neues Handle. Zumindest ist das bei mir so.
Peter

Geändert von Jasocul ( 2. Nov 2018 um 13:01 Uhr) Grund: Eine inhaltliche Korrektur
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.010 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 12:41
Bitte benutze den Debugger und schaue dir an, was das CreateMutex zurückgibt. Es ist ein neues Handle. Zumindest ist das bei mir so.
Zitat:
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.
Das Handle ist ein neues, aber das dahinterliegende Mutex ist immer noch das selbe.
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.
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."

Geändert von Neutral General ( 2. Nov 2018 um 12:43 Uhr)
  Mit Zitat antworten Zitat
Schokohase

Registriert seit: 17. Apr 2018
769 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#9

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 12:53
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.
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.013 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#10

AW: Mutex zwischen 2 Prozessen

  Alt 2. Nov 2018, 12:56
@Michael:
Ja, du hast Recht. Es ist ein neues Handle auf das selbe Mutex. Dennoch muss das Handle wieder freigegeben werden.
Peter
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:43 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf