Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Synchronize blockiert Anwendung (https://www.delphipraxis.net/194552-synchronize-blockiert-anwendung.html)

norwegen60 6. Dez 2017 17:03

Synchronize blockiert Anwendung
 
Hallo zusammen,

ich bin gerade am verzweifeln und bin sicher, dass es nur irgendwo eine Kleinigkeit ist. Ich habe einen Treiber auf das Nötigste zusammengestrichen. Also nicht wundern, dass es etwas sinnfrei wirkt. Das Problem ist, dass ich in einer DLL einen Thread starte. Sobald der aber im Execute-Teill das Synchronize() aufruft, bleibt er an der Stelle hängen. Ursprünglich ist es aus Delphi XE, es hängt aber auch in XE 10.2. Hier der Code

Die dll
Delphi-Quellcode:
library UV;

uses
  SysUtils,
  Windows,
  Classes,
  uProcessUv in 'uProcessUv.pas',
  uThreadUv in 'uThreadUv.pas';

{$R *.res}

exports
  SetCommandW;

end.
Der Prozesshandler
Delphi-Quellcode:
unit uProcessUv;
interface

uses
  uThreadUv;

type
  TProcessUv = class
    procedure Start;
  private
    constructor Create;
    destructor Destroy; override;
    procedure ShowStatus(sValue:String);
  public
  end;

procedure SetCommandW; stdcall;

implementation

uses
  Sysutils;

var
  ThreadUV : TThreadUv;
  ProcessUv: TProcessUv;

procedure SetCommandW; stdcall;
// Erlaubt das Senden von Kommandos als WideString und gibt das Ergebnis ebendfalls als WideString zurück
begin
  if not assigned(ProcessUv) then
  begin
    ProcessUv := TProcessUv.Create;
    ProcessUv.Start;
  end;
end;

constructor TProcessUv.Create;
begin
  inherited;
end;

destructor TProcessUv.Destroy;
begin
  inherited;
end;

procedure TProcessUv.ShowStatus(sValue: String);
// Synchronisert Statusmeldung vom ThreadUVv
begin
//  Mach was mit sValue
end;

procedure TProcessUv.Start;
begin
  if not assigned (ThreadUv) then
  begin
    ThreadUv := TThreadUv.Create;
    // ThreadUv.StatusEvent := ProcessUv.ShowStatus;
    ThreadUv.Start;
  end;
end;

end.
Der Threadhandler
Delphi-Quellcode:
unit uThreadUv;
interface

uses
  Classes;

type
  TThreadString = procedure(sValue: String) of Object;

  TThreadUV = class(TThread)
  protected
    procedure Execute; override;
  private
    { Private-Deklarationen }
    FStatus:     String;
    FStatusEvent: TThreadString;
    procedure SyncStatusEvent;
  public
    property StatusEvent: TThreadString read FStatusEvent write FStatusEvent;
    constructor Create;
    destructor Destroy; override;
  end;

implementation

{ TThreadUV }

constructor TThreadUV.Create;
begin
  inherited Create(true); // muss auf true stehen damit Aufruf mit Start funktioniert
end;

destructor TThreadUV.Destroy;
begin
  Terminate;
  inherited;
end;

procedure TThreadUV.SyncStatusEvent;
// Übergeordneten Prozess Status mitteilen
begin
  if assigned(FStatusEvent) then
    FStatusEvent(FStatus);
end;

procedure TThreadUV.Execute;
begin
  FStatus := 'So ein Mist';
  Synchronize(syncStatusEvent); // Hier hängt es sich auf

  while not Terminated do
  begin
    sleep(500);
    Terminate;
  end;
end;

end.
und zuletzt der Aufruf
Delphi-Quellcode:
procedure SetCommandW; stdcall; external 'UV.dll';

procedure TForm6.Button1Click(Sender: TObject);
begin
  SetCommandW;
end;
Egal, ob ich an Synchronice etwas assigned habe oder nicht, hängt sich die Anwendung beim Aufruf von
Delphi-Quellcode:
Synchronize(syncStatusEvent);
auf

Kann mir jemand sagen was ich falsch mache.

Vielen Dank
Gerd

Der schöne Günther 6. Dez 2017 17:12

AW: Synchronize blockiert Anwendung
 
Guck mal, ich glaub ich kenne den Kerl:

http://www.delphipraxis.net/177923-thread-dll.html

himitsu 6. Dez 2017 17:37

AW: Synchronize blockiert Anwendung
 
Kompilierst du mit Laufzeitpackages oder ohne?

Wenn ohne, dann hat die DLL ihre eigene RTL/VCL und deren eigenen globalen Variablen.
Die EXE hat ebenfalls ihre eigene RTL/VCL/Variablen.
Also das Synchronize der DLL weiß nichts von der VCL in der EXE und kann demnach nicht richtig arbeiten.

* mit Laufzeitpackages die EXE und DLL kompilieren
* oder kein Synchronize in der DLL (z.B. per Callback in der EXE das Synchronize)
* oder siehe CheckSynchronize in Antwort #4 von http://www.delphipraxis.net/177923-thread-dll.html

norwegen60 6. Dez 2017 19:17

AW: Synchronize blockiert Anwendung
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1388111)
Guck mal, ich glaub ich kenne den Kerl:

http://www.delphipraxis.net/177923-thread-dll.html

Oh, Schitt, wie peinlich.
Das blöde ist, in der damaligen Anwendung habe ich es zum Laufen gebracht und gestern und heute eigentlich gleich implememtiert und jetzt hänge ich wieder an derselben Stelle.

Das Synchronize soll nicht rauf zur EXE sondern raus aus dem Thread un dim nächsten Schritt entweder auf eine ANzeige oder zur Exe.

norwegen60 6. Dez 2017 19:52

AW: Synchronize blockiert Anwendung
 
So jetzt habe ich mir angeschaut wie ich es damals gemacht habe. Letztlich habe ich das Synchronize aus dem Thread raus geschmissen und von außen direkt auf die Variablen zugegriffen. So wie man es bei einem Thread ja wohl eher nicht machen soll. Oder gelten in einer DLL andere Regeln?
D.h. mir fehlt eigentlich immer noch der korrekte Weg wie ich in einem Thread einen Wert veröffentliche und und ihn dann als Callback an die EXE zurück gebe.

jaenicke 6. Dez 2017 21:04

AW: Synchronize blockiert Anwendung
 
Du kannst Synchronize problemlos in einer DLL nutzen, wenn du das OnIdle aus der Anwendung durchreichst...
Das habe ich bei uns z.B. in die Standardschnittstelle für DLLs direkt eingebaut.

In der DLL rufst du dann einfach in der im OnIdle aufgerufenen exportierten Prozedur CheckSynchronize auf. Schon funktioniert Synchronize.

himitsu 6. Dez 2017 21:11

AW: Synchronize blockiert Anwendung
 
Alles, wo "gleichzeitig" mehr als ein Thread auf eine Variable zugreifen kann, egal ob EXE oder DLL, muß abgesichert werden.

Die genannten Interlocked-/Atom-Funktionen arbeiten "atomar", dass heißt, dass die Operation nur in einem CPU-Schritt erledigt werden, wo auch andere Threads während dieser Zeit keinen Zugriff haben.
Somit sind diese Operationen per se thread-safe, da nur Einer zur selben Zeit Zugriff hat.

Alles Andere muß über Sperren (z.B. CriticalSections) oder über Synchronisationsfunktionen (wo alle Operationen in einen eintigen Thread verschoben werden und somit er der Einzige ist) abgesichert werden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:04 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz