我必须在Delphi XE7中编写DLL。我想在DLL中使用TParallel.For。 DLL被加载到C ++应用程序中,一切正常。但是,当应用程序终止或调用FreeLibrary时,应用程序将挂起。如果我删除所有TParallel.For循环并用标准循环替换它们,应用程序将正常退出。
TParallel.For循环非常简单:
TParallel.For(0, inImage.Height -1,
Procedure(ty : integer)
begin
SomeProcedure(ty);
end);
如果我使用完全相同的代码创建一个Delphi应用程序,一切都很完美。
经过大量的研究和调试后,看起来有一个死锁阻止了C ++应用程序在调用FreeLibrary时退出,但我无法找到TParallel中的问题所在。
总结一下情况:
我的问题是:
还有其他人遇到过这种行为吗?
在这种情况下找到死锁的好调试策略是什么?
非常感谢任何建议。
更新
好的,所以如果你想要最小,完整和可验证的例子,请你走吧(谢谢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.
在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
}
回应非常有用的&#34;评论&#34;代码中存在缺陷&#34;和#34;自己调试&#34;,谢谢你,这就是我一直在做的事情。因此,如果此处没有任何帮助,我将尝试获得切换到OTL的权限,OTL在相关DLL中有效。
更新2
OTL完全符合预期。所以,是的,代码中有一个&#34;缺陷&#34;。我放弃。我将建议完全放弃Delphi,然后我们可以将所有内容转移到C ++和C#。这必须是一个更好的短期(和长期)解决方案。
答案 0 :(得分:3)
我见过类似的问题,虽然我使用的是Delphi 10.0 Seattle和Delphi EXE加载Delphi DLL。
无论如何,我想出的解决方案如下:
在您的Delphi DLL中,首先创建自己的线程池。
使用TParallel.For的重载版本,它将线程池对象作为其最后一个参数,并提供您自己的线程池对象。
在卸载Delphi DLL之前,请确保释放您的线程池对象。
这种方法为我解决了这个问题。
TParallel.For documentation:
http://docwiki.embarcadero.com/Libraries/Berlin/en/System.Threading.TParallel.For
伪代码示例:
MyPool: TThreadPool;
MyPool := TThreadPool.Create;
TParallel.For(1, Max, procedure (I: Integer)
begin
if IsPrime (I) then
TInterlocked.Increment (Tot);
end,
MyPool
);
MyPool.Free;