Delphi XE7 Android 创建线程错误 运行 大约 2000000 次后
Delphi XE7 Android Creating Thread Error After Running about 2000000 times
提前感谢您的宝贵时间。
最初是简单的代码post。
TSubThread的代码
TSubThread = class(TThread)
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;
procedure TSubThread.Execute;
begin
// do nothing
end;
constructor TSubThread.Create;
begin
inherited Create(True);
Self.FreeOnTerminate:= False;
end;
TMainThread的代码
TMainThread = class(TThread)
private
FCounterOK,
FCounterErr:int64;
function FGetCounterOK:Int64;
function FGetCounterErr:Int64;
protected
procedure Execute; override;
public
property CountOK:Int64 read FGetCounter;
property CountErr:Int64 read FGetCounterErr;
constructor Create;
destructor Destroy; override;
end;
function TMainThread.FGetCounterOK:Int64;
begin
result:= TInterlocked.Read(Self.FCounterOK);
end;
function TMainThread.FGetCounterErr:Int64;
begin
result:= TInterlocked.Read(Self.FCounterErr);
end;
procedure TMainThread.Execute;
const
CSTMaxThreads = 20;
var
i: Integer;
los:TArray<TSubThread>;
begin
try
while not Self.Terminated do
begin
//Create instance of TSubThread and append to DynArray
while Length(los) < CSTMaxThreads do
begin
try
l:= TSubThread.Create;
los:= los + [l];
l.Start;
TInterLocked.Increment(Self.FCounterOK);
except on E:System.SysUtils.Exception do
TInterLocked.Increment(Self.FCounterErr);
end;
end;
for i:= Length(los)-1 downto 0 do
begin
// Free thread Object
if los[i].Finished then
begin
los[i].DisposeOf;
los[i]:= nil;
Delete(los,i,1);
end;
end;
end;
finally
// MainThread Terminated, Free all.
for i := Length(los)-1 downto 0 do
begin
los[i].DisposeOf;
los[i]:= nil;
end;
delete(los,0,Length(los));
end;
end;
在 Android 平台 E.ToString = [=25] 上 运行 大约 1800000 ~ 2000000 次(通过 CounterOK 和 CounterErr 属性)后,TSubThread 的创建引发异常=]...并且相同的程序在 Windows 和 IOS 上运行完美。
代码有什么问题吗?
我相当确定这里的问题是您产生了太多的线程并且 运行 没有资源来支持它们的存在。一旦 Execute 完成但在实际底层线程被清理之前,TThread 设置完成。 DisposeOf 将调用析构函数,但这仍然只使用 WaitFor 来检查完成,因此可能仍会为底层线程留下未完成的清理。在所有平台上管理线程的销毁一直存在问题,我很确定您会发现这就是这里正在发生的事情。很长很长一段时间以来,我一直使用内部重用的线程池和 freeonterminate true 来避免此类问题。
提前感谢您的宝贵时间。
最初是简单的代码post。
TSubThread的代码
TSubThread = class(TThread)
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;
procedure TSubThread.Execute;
begin
// do nothing
end;
constructor TSubThread.Create;
begin
inherited Create(True);
Self.FreeOnTerminate:= False;
end;
TMainThread的代码
TMainThread = class(TThread)
private
FCounterOK,
FCounterErr:int64;
function FGetCounterOK:Int64;
function FGetCounterErr:Int64;
protected
procedure Execute; override;
public
property CountOK:Int64 read FGetCounter;
property CountErr:Int64 read FGetCounterErr;
constructor Create;
destructor Destroy; override;
end;
function TMainThread.FGetCounterOK:Int64;
begin
result:= TInterlocked.Read(Self.FCounterOK);
end;
function TMainThread.FGetCounterErr:Int64;
begin
result:= TInterlocked.Read(Self.FCounterErr);
end;
procedure TMainThread.Execute;
const
CSTMaxThreads = 20;
var
i: Integer;
los:TArray<TSubThread>;
begin
try
while not Self.Terminated do
begin
//Create instance of TSubThread and append to DynArray
while Length(los) < CSTMaxThreads do
begin
try
l:= TSubThread.Create;
los:= los + [l];
l.Start;
TInterLocked.Increment(Self.FCounterOK);
except on E:System.SysUtils.Exception do
TInterLocked.Increment(Self.FCounterErr);
end;
end;
for i:= Length(los)-1 downto 0 do
begin
// Free thread Object
if los[i].Finished then
begin
los[i].DisposeOf;
los[i]:= nil;
Delete(los,i,1);
end;
end;
end;
finally
// MainThread Terminated, Free all.
for i := Length(los)-1 downto 0 do
begin
los[i].DisposeOf;
los[i]:= nil;
end;
delete(los,0,Length(los));
end;
end;
在 Android 平台 E.ToString = [=25] 上 运行 大约 1800000 ~ 2000000 次(通过 CounterOK 和 CounterErr 属性)后,TSubThread 的创建引发异常=]...并且相同的程序在 Windows 和 IOS 上运行完美。 代码有什么问题吗?
我相当确定这里的问题是您产生了太多的线程并且 运行 没有资源来支持它们的存在。一旦 Execute 完成但在实际底层线程被清理之前,TThread 设置完成。 DisposeOf 将调用析构函数,但这仍然只使用 WaitFor 来检查完成,因此可能仍会为底层线程留下未完成的清理。在所有平台上管理线程的销毁一直存在问题,我很确定您会发现这就是这里正在发生的事情。很长很长一段时间以来,我一直使用内部重用的线程池和 freeonterminate true 来避免此类问题。