Ich muss eine DLL in Delphi XE7 schreiben. Ich möchte TParallel.For in der DLL verwenden. Die DLL wird in eine C++ - Anwendung geladen, wo alles funktioniert. Wenn die Anwendung jedoch beendet wird oder ein Aufruf von FreeLibrary erfolgt, hängt die Anwendung. Wenn ich alle TParallel.For-Schleifen lösche und sie durch Standardschleifen ersetze, wird die Anwendung normal beendet.Möglicher Deadlock beim Aufruf von FreeLibrary
Die TParallel.For Schleifen sind sehr einfach:
TParallel.For(0, inImage.Height -1,
Procedure(ty : integer)
begin
SomeProcedure(ty);
end);
Wenn ich eine Delphi-Anwendung mit genau dem gleichen Code zu erstellen, alles perfekt funktioniert.
Nach viel Forschung und Debugging sieht es aus wie ein Deadlock, der verhindert, dass die C++ Anwendung beendet wird, wenn FreeLibrary aufgerufen wird, aber ich kann nicht finden, wo das Problem in TParallel ist.
einfach die Situation zusammenfassen:
- Die TParallel.For alle kompletten Loops und die richtigen Ergebnisse erzielen.
- Derselbe TParallel.For-Code in einer Delphi-.exe funktioniert ordnungsgemäß.
- Die DLL wird geladen, und die Funktionen werden ordnungsgemäß in der C++ - Anwendung aufgerufen und ausgeführt.
- Die C++ - Anwendung wird ordnungsgemäß beendet, wenn keine TParallel.For-Schleifen vorhanden sind.
- Die C++ - Anwendung wird hängen, wenn TParallel.For-Schleifen vorhanden sind.
- Ich vermute, dass es einen Deadlock gibt, der auftritt, wenn FreeLibrary aufgerufen wird.
- Wenn ich die OTL-Threading-Bibliothek verwende, funktioniert alles wie es sollte.
Meine Fragen sind:
Hat jemand anderes dieses Verhalten erlebt?
Was ist eine gute Debugging-Strategie, um in dieser Situation einen Deadlock zu finden?
Jeder Rat wird sehr geschätzt.
UPDATE
OK, wenn Sie also Minimal, vollständig und überprüfbar Beispiel wollen, hier gehen Sie (danke Stephen Ball):
library ADelphiDLL;
uses
System.SysUtils, System.Classes, Threading, SyncObjs;
function IsPrime (N: Integer): Boolean;
var
Test: Integer;
begin
IsPrime := True;
for Test := 2 to N - 1 do
if (N mod Test) = 0 then
begin
IsPrime := False;
break; {jump out of the for loop}
end;
end;
function Prime(Max : integer) : boolean;
var
tot : integer;
begin
tot := 0;
TParallel.For(1, Max, procedure (I: Integer)
begin
if IsPrime (I) then
TInterlocked.Increment (Tot);
end);
return true;
end;
exports Prime;
begin
IsMultiThread := True;
end.
in C++:
#include "stdafx.h"
typedef bool(__stdcall *primesf)(int);
void main()
{
HINSTANCE hGetDLL = LoadLibrary(L"ADelphiDLL.dll");
primesf primes = (primesf)GetProcAddress(hGetProcIDDLL, "Primes");
bool result = primes(100);
FreeLibrary(hGetDLL);// <-- Hangs here forever
}
In Antwort auf die sehr "hilfreiche" Kommentare, "es gibt einen Defekt im Code" und "debug es selbst", danke, das ist, was ich schon zu lange gemacht habe. Also, wenn es hier keine Hilfe gibt, werde ich versuchen, die Erlaubnis zu bekommen, zu OTL zu wechseln, was in der fraglichen DLL funktioniert.
UPDATE 2
OTL funktioniert genau wie erwartet. Also, ja, es gibt einen "Defekt im Code". Ich gebe auf. Ich werde empfehlen, Delphi ganz aufzugeben und dann können wir alles nach C++ und C# verschieben. Das muss eine viel bessere kurze (und langfristige) Lösung sein.
Ich vermute, dass 'TParallel' einen Pool Thread erstellt und erfordert einige explizite Bereinigung zu stoppen Sie. Die ausführbare Datei von Delphi erkennt dieses Verhalten und führt eine Bereinigung durch, während die ausführbare Datei von C++ dies nicht tut. – VTT
Es gibt einen Fehler im Code. Nur du hast den Code. Ohne ein [mcve] können wir nur raten. Lass uns nicht raten. Entweder produzieren Sie ein [mcve] oder führen Sie selbst ein Debugging durch. –
Kein Grund aufzugeben und Leuten die Schuld zu geben, die versuchen zu helfen. Es scheint, dass Sie einen guten Kandidaten für einen QP-Bericht haben. Bitte machen Sie das und treten Sie auch der g + Delphi Developers Gruppe bei und melden Sie sie dort. David M ist dort aktiv und kann helfen. –