![]() |
AsyncCalls 2.91 - Asynchrone Funktionsaufrufe in Delphi
Liste der Anhänge anzeigen (Anzahl: 1)
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.
![]() 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; |
Re: AsyncCalls - Asynchrone Funktionsaufrufe in Delphi
Hallo!
OK... Du hast also eine Unit geschrieben, die eigene Threads erzeugt? Kannst Du nochmal erklären, wofür und was das bringen soll? Was ist mit dem Sync für Ausgaben? Was ist mit "Threadsave Code"? Sorry, vielleicht brauche ich heute morgen auch nur erst mal einen Kaffee... :-) Grüsse Frank PS.: Klingt aber spannend.... |
Re: AsyncCalls - Asynchrone Funktionsaufrufe in Delphi
Zitat:
Zitat:
Delphi-Quellcode:
Da das Netzwerk aber nicht besonders schnell ist, verbringt man eine ganze Menge an Zeit untätig wenn der erste Download ewig dauert, wobei der zweite recht schnell ist.
DownloadFile('http://sonstwo.de/file1.html', Stream);
Verarbeite(Stream); DownloadFile('http://sonstwo.de/file2.html', Stream2); Verarbeite(Stream2); Mit AsyncCalls kann man das z.B so schreiben (wobei das sicherlich nicht der Weisheit letzter Schluss ist):
Delphi-Quellcode:
Syntaktische Korrektheit ist nicht gegeben
procedure DownloadFileAsync(const Url: string; Stream: TStream); cdecl;
begin DownloadFile(Url, Stream); end; for i := 0 to Urls.Count - 1 do begin // beide Downloads starten a := AsyncCall(@DownloadFileAsync, [Urls[i], Streams[0]]); b := AsyncCall(@DownloadFileAsync, [Urls[i], Streams[1]]); Index := AsyncWaitSync([a, b], False); // warten bis mindestens ein AsyncCall beendet ist Verarbeite(Streams[Index]); // den ersten beendeten Download verarbeiten AsyncWaitSync([a, b], True); // auf den anderen Download warten Verarbeite(Streams[(Index + 1) mod 2]); end; Zitat:
Zitat:
Delphi-Quellcode:
type
TData = record s: string; i: Integer; end; procedure DoSomething(var Data: TData); begin Data.s := 'Hallo'; Data.i := 10; Sleep(100); // ein wenig Zeit verplempern. end; var d: TData; a: IAsyncCall; begin a := AsyncCallEx(@DoSomething, d); // irgendwas anderes machen ... a.Sync; ShowMessage(d.s + ': ' + IntToStr(d.i)); end; |
Re: AsyncCalls - Asynchrone Funktionsaufrufe in Delphi
Eine Sache verstehe ich nicht (oder vielleicht sehe ich ein Problem
das es gar nicht gibt). Du übergibst die Parameter als ein Array of Const. Ich weiss nicht mit Sicherheit wie Delphi so ein Array verwaltet (kopiert er etwa alles auf den Stack?) aber üblicherweise ist ein "const" Parameter ein Pointer. VAR x:tstringlist; begin x:=tstringlist.create; x.add('test'); AsyncCall (@meinproc, [X]); x.add('Hallo'); bekommt "meinproc" nun 1 oder 2 Strings zu verdauen? |
Re: AsyncCalls - Asynchrone Funktionsaufrufe in Delphi
Zitat:
Zitat:
|
Re: AsyncCalls - Asynchrone Funktionsaufrufe in Delphi
Da ich heute in einen schweren Bug gelaufen bin, der durch einen Bug in TThread.Resume ausgelöst wurde, habe ich die AsyncCalls Unit um einen Workaround aktualisiert.
Der Fehler äußert sich dahingehend, dass es beim Beenden der Anwendung auf ein bereits freigegebenes Thread-Objekt durch TThread.Resume (schreibend) zugegriffen wird. |
Re: AsyncCalls - Asynchrone Funktionsaufrufe in Delphi
Wieso nennst du das synchron/asynchron? Wäre seriell/parallel nicht eine viel bessere Ausdrucksweiße?
Seriell ist das bearbeiten von Downloads nach und nach. Und Parallel ist das, was deine "ASync" Methodik macht. |
Re: AsyncCalls 2.9 - Asynchrone Funktionsaufrufe in Delphi
Es gibt nun auch eine neue Version von AsyncCalls 2.9. Diese behebt einige Fehler und nutzt Generics und anonyme Methoden. Das Beispiel auf der ersten Seite habe ich aktualisiert.
|
Re: AsyncCalls - Asynchrone Funktionsaufrufe in Delphi
Zitat:
|
Re: AsyncCalls 2.9 - Asynchrone Funktionsaufrufe in Delphi
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 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 by Thomas Breitkreuz