gpt4 book ai didi

Delphi 无法使用对象引用执行任务中的过程

转载 作者:行者123 更新时间:2023-12-03 01:49:24 26 4
gpt4 key购买 nike

我有一个简单的类,它具有以下接口(interface)实现。

注意:TPolyBase是一个抽象类并且 TPolyResultarray of double ;查看他们的代码并不重要,与这里无关。

//INTERFACE

type
TPolynomialList = class
strict private
FPolynomialList: TObjectList<TPolyBase>;
FResult: TList<TPolyResult>;
FCanGet: boolean;
function GetResult: TList<TPolyResult>;
procedure DoSolve;
public
constructor Create(PolynomialList: TObjectList<TPolyBase>);
destructor Destroy; override;

procedure SolvePolynomials(CompletionHandler: TProc);
property Solutions: TList<TPolyResult> read GetResult;
end;

//IMPLEMENTATION

constructor TPolynomialList.Create(PolynomialList: TObjectList<TPolyBase>);
begin
FPolynomialList := PolynomialList;
FResult := TList<TPolyResult>.Create;
FCanGet := false;
end;

destructor TPolynomialList.Destroy;
begin
FResult.Free;
inherited;
end;

procedure TPolynomialList.DoSolve;
var
i: integer;
begin
for i := 0 to FPolynomialList.Count - 1 do
FResult.Add(FPolynomialList[i].GetSolutions);

FCanGet := true;
end;

function TPolynomialList.GetResult: TList<TPolyResult>;
begin
if FCanGet = false then
raise TEquationError.Create('You must solve the equation first!');

Result := FResult;
end;

procedure TPolynomialList.SolvePolynomials(CompletionHandler: TProc);
begin
TTask.Run(procedure
var
ex: TObject;
begin
try
DoSolve;
TThread.Synchronize(nil, procedure
begin
CompletionHandler;
end);
except
on E: Exception do
begin
ex := AcquireExceptionObject;
TThread.Synchronize(nil, procedure
begin
Writeln( (ex as Exception).Message );
end);
end;
end;
end);
end;

此类接受对象列表作为输入,它有一个名为 FResult 的内部重要字段。将结果提供给用户。仅当 SolvePolynomials 方法完成其工作后才能从 getter 访问它。


问题出在 SolvePolynomials 。我展示的代码使用了一个任务,因为对象列表的大小可能非常大,而且我不想卡住 UI。为什么我总是在任务代码中遇到访问冲突?

请注意,以下代码工作正常,但这不是我想要的,因为如果我输入 15000,程序会卡住几秒钟。

procedure TPolynomialList.SolvePolynomials(CompletionHandler: TProc);
begin
DoSolve;
CompletionHandler;
end;

可以 FPolynomialList变量是一个问题吗?如果你看看我的类(class),唯一“从外部获取”的就是 TObjectList<TPolyBase>因为在构造函数中我只是简单地分配引用(我想避免复制 15k 项)。所有其他变量不与任何东西共享。

我在我读过的很多书中都看到过,比如“Delphi High Performance”,有一个调用内部“慢”方法的任务是很好的,但在这种情况下,可能会有那些引用搞乱了某些东西。任何想法?


这是我用作测试的代码:

var
a: TObjectList<TPolyBase>;
i, j: integer;
f: TPolynomialList;
s: string;

function GetRandom: integer;
begin
Result := (Random(10) + 1);
end;

begin
a := TObjectList<TPolyBase>.Create(true);
try

for i := 0 to 15000 do
begin
a.Add({*Descendant of TPolyBase*})
end;


f := TPolynomialList.Create(a);
try
f.SolvePolynomials(procedure
var
i, j: integer;
begin
for i := 0 to f.Solutions.Count - 1 do
begin
for j := Low(f.Solutions[i]) to High(f.Solutions[i]) do
Writeln({output the results...})
end;
end);
finally
f.Free;
end;

finally
a.Free;
end;

end.

最佳答案

您的 SolvePolynomials 方法将求解委托(delegate)给另一个线程,并在该线程完成其任务之前返回。当该任务线程正在运行时,它所操作的所有数据都必须保持事件状态。但是,在您的代码中,您在 SolvePolynomials 退出后立即释放必要的对象实例 - 而您的任务仍在运行,因此会出现错误。

您必须将这些对象的释放移至完成处理程序中。

基本上,您的代码简化后如下所示:

type
TPolynomialList = class
public
destructor Destroy; override;
procedure DoSolve;
procedure SolvePolynomials(CompletionHandler: TProc);
end;

destructor TPolynomialList.Destroy;
begin
Writeln('Destroyed');
inherited;
end;

procedure TPolynomialList.DoSolve;
begin
Writeln('Solving');
end;

procedure TPolynomialList.SolvePolynomials(CompletionHandler: TProc);
begin
TTask.Run(
procedure
begin
try
DoSolve;
TThread.Synchronize(nil,
procedure
begin
CompletionHandler;
end);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end);
end;

procedure Test;
var
f: TPolynomialList;
begin
f := TPolynomialList.Create;
try
f.SolvePolynomials(
procedure
begin
Writeln('Solved');
end);
finally
f.Free;
end;
end;

如果运行它,输出将是:

Destroyed
Solving
Solved

但是,如果将变量的释放移至完成处理程序中,执行顺序将是正确的。

procedure Test;
var
f: TPolynomialList;
begin
f := TPolynomialList.Create;
f.SolvePolynomials(
procedure
begin
Writeln('Solved');
f.Free;
end);
end;

Solving
Solved
Destroyed

对于您的代码,这意味着将 a.Freef.Free 移动到完成处理程序中。

关于Delphi 无法使用对象引用执行任务中的过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52187717/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com