AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte AsyncCalls 2.91 - Asynchrone Funktionsaufrufe in Delphi
Thema durchsuchen
Ansicht
Themen-Optionen

AsyncCalls 2.91 - Asynchrone Funktionsaufrufe in Delphi

Ein Thema von jbg · begonnen am 15. Dez 2006 · letzter Beitrag vom 17. Mär 2009
Antwort Antwort
Seite 3 von 3     123   
jbg
Registriert seit: 12. Jun 2002
Mit meiner neuesten Erschaffung (AsyncCalls) kann man nun sehr leicht und ohne großen Aufwand mehreren Funktionen und Methoden zur gleichen Zeit ausführen und diese auch noch synchronisieren. Dazu ist nicht mehr notwendig, als eine der AsyncCall() Funktionen aufzurufen. Diese liefert dann ein IAsynCall Interface zurück mit dem der asynchrone Funktionsaufruf wieder synchronisiert werden kann. Da es sich um ein Interface handelt, wird beim Verlassen der Funktion/Methode auf alle noch ausstehenden asynchronen Funktionen gewartet.

Homepage, Download und Beschreibung

Beispielcode (Einlesen von drei Verzeichnissen in asynchronen Funktionen):
Delphi-Quellcode:
function TFormMain.DoSomething(Value: TObject): Integer;
begin
  Result := 0;
end;

procedure TFormMain.Button3Click(Sender: TObject);
var
  Value: Integer;
begin
  // TAsyncCalls.Invoke<TObject>(DoSomething, nil); wegen internal compiler error nicht mehr funktionsfähig

  TAsyncCalls.Invoke(procedure
  begin
    Value := 10;
    TAsyncCalls.VCLInvoke(procedure
    begin
      ShowMessage('Der Werk könnte ungleich 10 sein: ' + IntToStr(Value));
    end);
    Value := 20;
    TAsyncCalls.VCLSync(procedure
    begin
      ShowMessage('Der Wert ist 20: ' + IntToStr(Value));
    end);
    Value := 30;
  end).ForceDifferentThread;

  Sleep(1000);
end;
Delphi-Quellcode:
{ Die cdecl Funktion GetFiles() besitzt zwei Parameter vom Typ string und object, die hier ganz normal deklariert werden. }
procedure GetFiles(const Directory: string; Filenames: TStrings); cdecl;
var
  h: THandle;
  FindData: TWin32FindData;
begin
  h := FindFirstFile(PChar(Directory + '\*.*'), FindData);
  if h <> INVALID_HANDLE_VALUE then
  begin
    repeat
      if (StrComp(FindData.cFileName, '.') <> 0) and (StrComp(FindData.cFileName, '..') <> 0) then
      begin
        Filenames.Add(Directory + '\' + FindData.cFileName);
        if FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
          GetFiles(Filenames[Filenames.Count - 1], Filenames);
      end;
    until not FindNextFile(h, FindData);
    Windows.FindClose(h);
  end;
end;

procedure TFormMain.ButtonGetFilesClick(Sender: TObject);
var
  Dir1, Dir2, Dir3: IAsyncCall;
  Dir1Files, Dir2Files, Dir3Files: TStrings;
begin
  Dir1Files := TStringList.Create;
  Dir2Files := TStringList.Create;
  Dir3Files := TStringList.Create;
  ButtonGetFiles.Enabled := False;
  try
    { Die beiden Parameter der GetFiles() Funktion werden mittels eines const array of const übergeben }
    Dir1 := AsyncCall(@GetFiles, ['C:\Windows', Dir1Files]);
    Dir2 := AsyncCall(@GetFiles, ['D:\Html', Dir2Files]);
    Dir3 := AsyncCall(@GetFiles, ['E:', Dir3Files]);

    { Warten bis die beiden asynchronen Funktion beenden sind. Während dieser Zeit dem die UI nicht einfrieren lassen }
    while AsyncMultiSync([Dir1, Dir2], True, 10) < 0 do
      Application.ProcessMessages;
    Dir3.Sync; // Auf die Beendigung der Dir3 Funktion warten

    MemoFiles.Lines.Assign(Dir1Files);
    MemoFiles.Lines.AddStrings(Dir2Files);
    MemoFiles.Lines.AddStrings(Dir3Files);
  finally
    ButtonGetFiles.Enabled := True;
    Dir3Files.Free;
    Dir2Files.Free;
    Dir1Files.Free;
  end;
end;
Angehängte Dateien
Dateityp: zip asynccalls_138.zip (32,2 KB, 46x aufgerufen)
 
Benutzerbild von sirius
sirius

 
Delphi 7 Enterprise
 
#21
  Alt 1. Dez 2008, 18:12
Er wirft c ja nicht weg, er hat es eigentlich nur nie gehabt. Er benutzt es nur in den Registern.
  Mit Zitat antworten Zitat
jbg

 
Delphi 10.1 Berlin Professional
 
#22
  Alt 1. Dez 2008, 18:13
Schalte mal die Stackframes für die Funktion an. Einfach vor die Methode ein {$STACKFRAMES ON} und danach ein {$STACKFRAMES OFF}.
Andreas aka AHUser aka jbg
  Mit Zitat antworten Zitat
BloodySmartie
 
#23
  Alt 2. Dez 2008, 09:17
Mit Stackframes bekomme ich nun in dem weiter unten gelegenen Codeabschnitt beim Zugriff auf den Hauptthread eine Schutzverletzung:
Delphi-Quellcode:
 if c>0 then begin
    EnterMainThread;
    try
      log(inttostr(c)+' Automat(en) von Mandant '+clientData.cname+' gelöscht, Laufzeit '+inttostr(et-st)+' ms ',1);
      dispatcherForm.deletedMachinesLED.Status:=false; // <---- Schutzverletzung tritt hier auf
      dispatcherform.lDeletedMachineLED.Caption:='Suche nach gelöschten Automaten (letzte Laufzeit: '+inttostr(et-st)+' ms )';
    finally
      LeaveMainThread;
    end;

  end;
Nachtrag:

Die Schutzverletzung tritt in Unit System auf, in Methode TObject.InheritsFrom
  Mit Zitat antworten Zitat
BloodySmartie
 
#24
  Alt 5. Feb 2009, 17:23
Zwar konnte ich meinen Fehler aus dem letzten Post nicht mehr wirklich ausfindig machen aber ich habe inzwischen noch etwas gefunden, das mich stutzig macht. Meine Anwendung, die zwei oder mehr asynchrone Aufrufe derselben Prozedur gleichzeitig laufen lässt, hängt sich auf, sobald in der Prozedur ein exit aufgerufen wird. Das passiert übrigens nicht sofort, sondern vielmehr nach 50-100 Aufrufen.

In der Unit asynccalls, wie auch hier, konnte ich nur von Problemen mit Exit innerhalb eines EnterMainThread-LeaveMainThread - Blocks lesen, das aber auch gelöst zu sein scheint. Um nicht wieder als doof abgestempelt zu werden: Was ist mein Fehler? Ich würde mich wirklich freuen, wenn mir das jemand erklären würde.
  Mit Zitat antworten Zitat
jbg

 
Delphi 10.1 Berlin Professional
 
#25
  Alt 5. Feb 2009, 18:31
Da ich deinen Code nicht kenne, kann ich nur Rätseln woran das liegen kann. Das kann von Speicherüberschreibungen deines Codes bis zu glattem Fehlverhalten meines Codes reichen.

Zitat von BloodySmartie:
Meine Anwendung, die zwei oder mehr asynchrone Aufrufe derselben Prozedur gleichzeitig laufen lässt
Ich hoffe, dass du nicht annimmst, dass AsyncCall gemeinsame Variable schützt.

Ansonsten würde ich dir zu den TAsyncCalls.Invoke() bzw. TAsyncCalls.VCLSync() / TAsyncCalls.VCLInvoke() Methoden raten, denn die basieren nicht auf Annahmen über den kompilierten Code. Wahrscheinlich generiert der Compiler bei dir einen Code der von den alten AsyncCalls Methoden nicht behandelt wird/werden kann.

Delphi-Quellcode:
EnterMainThread;
try
  bla;
finally
  LeaveMainThread;
end;
Wir mit den neuen Methoden zu:
Delphi-Quellcode:
TAsyncCalls.VCLSync(procedure
  begin
    bla;
  end);
Andreas aka AHUser aka jbg
  Mit Zitat antworten Zitat
BloodySmartie
 
#26
  Alt 6. Feb 2009, 01:08
Das Ganze lässt sich in wenigen Zeilen reproduzieren. Ich lade morgen mal ein kleines Testprojekt hoch, sobald ich auf Arbeit bin.

Beste Grüße,

David
  Mit Zitat antworten Zitat
MStoll

 
Turbo Delphi für Win32
 
#27
  Alt 16. Mär 2009, 20:42
Hallo,

ich möchte dem Autor für diese Arbeit ein großes Lob aussprechen. Wirklich ein sehr nützliches und gut funktionierendes Tool.
Dafür vielen Dank!

Gruß
Michael
  Mit Zitat antworten Zitat
Dezipaitor

 
Delphi 7 Professional
 
#28
  Alt 17. Mär 2009, 22:31
Warum hört die VCL auf, auf Eingaben zu reagieren, wenn ich Invoke oder AsynCall aufrufe? Ich dachte, das geht alles über Threads? Die Funktion springt ja auch sofort zurück, aber eine Form reagiert nicht mehr.

Was man immer machen muss ist:
Delphi-Quellcode:
while AsyncMultiSync([x], True, 10) = WAIT_TIMEOUT do
  Application.ProcessMessages;
Aber muss das wirklich so sein?
Christian
  Mit Zitat antworten Zitat
Dezipaitor

 
Delphi 7 Professional
 
#29
  Alt 17. Mär 2009, 22:36
Zitat von jbg:
Da es sich um ein Interface handelt, wird beim Verlassen der Funktion/Methode auf alle noch ausstehenden asynchronen Funktionen gewartet.
Ha, selbst beantwortet.
Christian
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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 20:26 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