Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   DLL und Callback-Funktion: Hostprogramm reagiert nicht? (https://www.delphipraxis.net/175066-dll-und-callback-funktion-hostprogramm-reagiert-nicht.html)

romber 29. Mai 2013 15:26

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1216845)
Nochmal von vorne...
  1. Client "Hauptprogramm" bindet DLL ein
  2. Hauptprogramm erzählt der DLL, welche Funktion es später einmal aufrufen soll, wenn es Datenmengen abzugeben hat
  3. Die DLL tut viele Dinge, darunter auch mehrere Threads öffnen
  4. Mehrere der Threads aus der DLL entscheiden sich nun innerhalb einer kurzen Zeitspanne, die Datenablieferungsfunktion aufzurufen
  5. Die Funktion soll erst einmal nichts anderes tun, als die Daten, die sie übergeben bekommt, als Text in eine Memo zu werfen

Alles richtig bis hier?

Genau so ist es. Wohlgemerkt dass es sich bei dem Hostprogramm nur um eine kleine Testanwendung handelt.

Zitat:

Zitat von Der schöne Günther (Beitrag 1216845)
Wenn ich zumindest das Problem verstehe, dann ist es die Tatsache, dass (der Thread aus) der DLL mit der ganzen VCL-Geschichte des Hauptprogramms nichts am Hut hat. Und somit beispielsweise auch erst garnichts im Kontext des Hauptthreads ausführen kann. Richtig?

Aber die DLL greifft doch auf die Callback-Funktion zu, die wiederum auf die TMemo zugreifft. Oder habe ich die Frage falsch verstanden?

Zitat:

Zitat von Der schöne Günther (Beitrag 1216845)
Ich würde die Datenablieferungsfunktion so bauen, dass hier Daten einfach nur abgelegt werden. Beispielsweise in einer verketteten Liste (natürlich entsprechend geschützt, z.B. mit einem kritischen Abschnitt). In deinem Hauptprogramm würde ich z.B. jede halbe Sekunde hingehen und schauen, ob mittlerweile neue Daten vorliegen. Wenn ja, kann man die ja anzeigen.

In dem eingentlichen Client wird das auch so sein. Die Daten werden von der Callback-Funktion aufbereitet und einem s.g. Custom Date Source hinzugefügt, das wiederrum einen TObejctList als Datencontainer benutzt. Kommen neue Daten an, ruft Custom Data Source eine Funktion auf, die die neue Daten im Grid anzeigt.

Trotzdem würde ich gerne wissen, warum sich das Testprogramm aufhängt.

Bummi 29. Mai 2013 16:15

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
Nur schnell zusammengestöpselt, ein Rumpf , Fehlerkorrektur erbeten ...


DLL

Delphi-Quellcode:
library Project2;

uses
  SysUtils,
  Classes;

Type

   TCallBackProc=Procedure(info:PChar);
   TDummyThread=Class(TThread)
     Procedure Execute;override;
   End;

{$R *.res}
Var
  SaveExit:Pointer;
  TheCallBackProc:TCallBackProc;

procedure LibExit;far;
begin
     ExitProc := SaveExit;
end;


Procedure InitDLL(CallBackProc:TCallBackProc);
var
 i:Integer;
begin
   TheCallBackProc := CallBackProc;
   for I := 0 to 100 do
     with TDummyThread.Create(false) do FreeOnTerminate := true;
end;

exports
InitDLL index 1;

{ TDummyThread }

procedure TDummyThread.Execute;
begin
  inherited;
  Sleep(Random(2000));
  if Assigned(TheCallBackProc) then TheCallBackProc(PChar(Format('Irnedein Testtext %d',[ThreadID])));
end;

begin
     SaveExit := ExitProc;
     ExitProc := @LibExit;
end.

Testprogramm


Delphi-Quellcode:
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
   TCallBackProc=Procedure(info:PChar);
   TInitDLL=Procedure (p:TCallBackProc);

  TForm3 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    FH:Thandle;
    FInitDLL:TInitDLL;

  public
    { Public-Deklarationen }
  end;

var
  Form3: TForm3;

implementation
{$R *.dfm}
procedure SyncAddToMemo(const s:String);
begin
  Form3.Memo1.Lines.add(s);
  Application.ProcessMessages;
end;


procedure CallBack(P:PChar);
begin
    TThread.Synchronize(nil,Procedure begin SyncAddToMemo(P) end)
end;



procedure TForm3.Button1Click(Sender: TObject);
begin
  if Assigned(FInitDLL) then FInitDLL(@CallBack);
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
   FH := LoadLibrary(Pchar(ExtractFilePath(Paramstr(0))+'Project2.dll'));
   if FH<>0 then
       FInitDLL := GetProcAddress(FH,'InitDLL');

end;

procedure TForm3.FormDestroy(Sender: TObject);
begin
  if FH<>0 then FreeLibrary(FH);

end;

end.

Sir Rufo 29. Mai 2013 16:20

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
@bummi

Mach aus dem
Delphi-Quellcode:
TThread.Synchronize
ein
Delphi-Quellcode:
TThread.Queue
und das
Delphi-Quellcode:
Application.ProcessMessages
kannst du unter den Tisch fallen lassen ;)

Obwohl ich sowieso nicht sehe, wozu das wirklich gut sein soll ... :gruebel:

jaenicke 29. Mai 2013 16:21

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
Hast du denn mal die Trial von Eurekalog oder MadExcept ausprobiert (installiert und für beide Projekte, also Hauptprogramm und DLL, aktiviert)? Du musst die ja nicht sofort kaufen, sondern kannst es erst einmal ausprobieren. Du wirst aber denke ich merken, dass die durchaus sehr hilfreich sind und ihr Geld wert sind.

Denn das Programm hängt sich deinem Screenshot zufolge ja nicht auf, sondern hat einfach eine unbehandelte Exception. Die findest du auch in den Dr. Watson Debuglogs, sofern die auf deinem PC aktiviert gelassen sind. Den Stacktrace bekommst du da aber nur in aufbereiteter Form, wenn du .dbg Dateien aus den Delphi-Debugdateien erzeugst.

Bummi 29. Mai 2013 16:39

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
@SirRufo für Queue müsste ich den Thread als Object aus der DLL zurückgeben.
Der Hintergrund was eigentlich nur zu zeigen wo IMHO synchronisiert werden muss.

Sir Rufo 29. Mai 2013 17:08

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
Zitat:

Zitat von Bummi (Beitrag 1216883)
@SirRufo für Queue müsste ich den Thread als Object aus der DLL zurückgeben.
Der Hintergrund was eigentlich nur zu zeigen wo IMHO synchronisiert werden muss.

Nö, geht genauso wie mit dem Sychronize ;) (liegen beide als
Delphi-Quellcode:
class procedure
vor)

http://docwiki.embarcadero.com/Libra....TThread.Queue
http://docwiki.embarcadero.com/Libra...ad.Synchronize

Bummi 29. Mai 2013 17:46

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
@SirRufo ich lasse mich gerne belehren ich hatte den Fehler bei der Übergabe von nil auf den fehlenden Thread bezogen.
Du hast recht dieser muss nicht übergeben werden, trotzdem fliegt mir das ganze bei ausreichender Threadanzahl mit Queue um die Ohren, ich vermute weil der übergebene PChar bis zum abarbeiten der Queue ungültig geworden ist.

jaenicke 29. Mai 2013 18:12

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
Deshalb nimmt man da ja auch keinen PChar, sondern z.B. einen WideString, wenn etwas asynchron weiterverarbeitet wird.

Sir Rufo 29. Mai 2013 19:09

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
Wenn der PChar in einer lokalen string Variable gespeichert wird dann sollte dieser auch problemlos per Queue weitergegeben werden können.

Widestring ist da natürlich wesentlich nkomplizierter :)

jaenicke 30. Mai 2013 10:10

AW: DLL und Callback-Funktion: Hostprogramm reagiert nicht?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1216906)
Wenn der PChar in einer lokalen string Variable gespeichert wird dann sollte dieser auch problemlos per Queue weitergegeben werden können.

Da bin ich mir nicht so sicher. Wenn du einen PChar nach dem TThread.Queue noch veränderst, wird ja in der Prozedur in der Schlange auch der veränderte Wert benutzt. Einfaches Beispiel:
Delphi-Quellcode:
procedure TTest.Execute;
var
  a: PChar;
begin
  a := PChar(DupeString('f', 30)); // um keine Konstante zu haben
  TThread.Queue(nil, procedure
    begin
      ShowMessage(a); // fdsdfsd
    end);
  a := 'fdsdfsd';
end;
Wo da wirklich der Speicher freigegeben wird, wäre ich mir jetzt nicht so sicher...
(und ich habe grad keine Lust zu schauen ;-))


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:48 Uhr.
Seite 2 von 2     12   

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