Ich versuche, eine Netbios-Suche in einem gesamten Subnetz der Klasse C durchzuführen, indem ich AsyncCalls . Im Idealfall würde ich gerne 10 + Lookups gleichzeitig durchführen, aber es ist derzeit nur 1 Lookup zu einer Zeit. Was mache ich hier falsch?
Mein Formular enthält 1 Schaltfläche und 1 Memo.
%Vor%Tricky Zeug. Ich habe ein Debugging durchgeführt (naja, einiges Debuggen) und herausgefunden, dass der Code in AsyncCallsEx in Zeile 1296 blockiert:
%Vor%Weiteres Graben hat gezeigt, dass es in der Interface-Kopie in System.pas (_IntfCopy) bei
blockiert %Vor%Wenn wir uns die Pascal-Version des gleichen Codes ansehen, scheint diese Zeile den Referenzzähler freizugeben, der zuvor im Zielparameter gespeichert wurde. Ziel ist jedoch ein Ergebnis, das nicht im Aufrufer (Ihrem Code) verwendet wird.
Jetzt kommt der schwierige Teil.
AsyncCallEx gibt eine Schnittstelle zurück, die (in Ihrem Fall) vom Aufrufer weggeworfen wird. In der Theorie sollte also der kompilierte Code (in Pseudoform) so aussehen
%Vor%Der Compiler optimiert dies jedoch auf
%Vor%Warum? Weil es weiß, dass das Zuweisen der Schnittstelle die Referenzzahl der in der tmp-Variablen gespeicherten Schnittstelle automatisch freigibt (der Aufruf von _Release in _IntfCopy). Daher müssen Sie _Release nicht explizit aufrufen.
Das Freigeben von IAsyncCall bewirkt jedoch, dass der Code auf die Beendigung des Threads wartet. Sie warten also im Grunde, dass der vorherige Thread bei jedem Aufruf von AsyncCallEx beendet wird ...
Ich weiß nicht, wie ich das mit AsyncCalls lösen kann. Ich habe diesen Ansatz versucht, aber irgendwie funktioniert es nicht vollständig wie erwartet (Programm blockiert nach dem Pingen von etwa 50 Adressen).
%Vor% Wenn Sie AsyncCallEx()
oder eine andere der AsyncCalls-Funktionen aufrufen, erhalten Sie einen IAsyncCall
-Schnittstellenzeiger. Wenn der Referenzzähler 0
erreicht, wird das zugrundeliegende Objekt zerstört, was auf den Abschluss des Worker-Thread-Codes wartet. Sie rufen AsyncCallEx()
in einer Schleife auf, dh jedes Mal, wenn der zurückgegebene Schnittstellenzeiger derselben (verborgenen) Variablen zugewiesen wird, wird der Referenzzähler dekrementiert und das vorherige asynchrone Aufrufobjekt wird synchron freigegeben.
Um dies zu umgehen, fügen Sie einfach ein eigenes Array von IAsyncCall
zur Form-Klasse hinzu:
und weisen Sie die zurückgegebenen Schnittstellenzeiger den Array-Elementen zu:
%Vor%Dies hält die Schnittstellen am Leben und ermöglicht die parallele Ausführung.
Beachten Sie, dass dies nur die allgemeine Idee ist, dass Sie Code hinzufügen müssen, um das entsprechende Arrayelement zurückzusetzen, wenn ein Anruf zurückkehrt, und warten Sie, bis alle Aufrufe abgeschlossen sind, bevor Sie das Formular freigeben.
Tags und Links multithreading delphi