gpt4 book ai didi

delphi - 如何在Delphi中异步调用函数/过程(无组件)

转载 作者:行者123 更新时间:2023-12-03 14:42:39 29 4
gpt4 key购买 nike

我正在尝试在 Delphi 中异步运行函数或过程,但不使用组件,有没有办法使用 Delphi 核心函数来实现这一点?

最佳答案

如果你问VCL有没有东西like BeginInvoke in .NET开箱即用,那么答案是否定的。但是,您可以以链接到程序的小单元的形式获得非常相似的东西,即AsyncCalls。安德烈亚斯·豪斯拉登的图书馆。它不是一个组件,所以我想它符合资格。它还支持 Delphi 从版本 5 开始。非常推荐。

编辑:

我将添加一个示例,因为您没有运行它。如果您在调用代码中遇到阻塞,那么您的问题是没有保留对该函数返回的 IAsyncCall 接口(interface)指针的引用。因此,当临时引用超出范围时,实现该接口(interface)的对象将立即被销毁。析构函数将在 VCL 线程的上下文中调用,并且它将调用 WaitForSingleObject() 或类似的函数来等待工作线程完成。其结果是您的 VCL 线程被阻塞。

如果您维护对接口(interface)指针的引用,您将获得正确的行为:

type
TForm1 = class(TForm)
Button1: TButton;
Timer1: TTimer;
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
fAsyncCall: IAsyncCall;
procedure WaitForIt(ADelay: integer);
end;

将计时器设置为禁用,并使其具有非常短的间隔,例如 50 毫秒。单击按钮开始异步操作:

procedure TForm1.Button1Click(Sender: TObject);
begin
Button1.Enabled := FALSE;
fAsyncCall := AsyncCall(WaitForIt, 1000);
end;

procedure TForm1.WaitForIt(ADelay: integer);
begin
Sleep(ADelay);

EnterMainThread;
try
Randomize;
Color := RGB(Random(256), Random(256), Random(256));
Timer1.Enabled := TRUE;
finally
LeaveMainThread;
end;
end;

当该操作处于事件状态时,无法启动其他操作。完成后,它使计时器能够通知表单并重置接口(interface)引用:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := FALSE;
Assert((fAsyncCall <> nil) and fAsyncCall.Finished);
fAsyncCall := nil;
Button1.Enabled := TRUE;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := (fAsyncCall = nil) or fAsyncCall.Finished;
end;

请注意,如何通过使用 EnterMainThread()LeaveMainThread() 直接从被调用的方法访问表单。

上面的代码并不是绝对的最小值,它只是为了演示一些想法。

关于delphi - 如何在Delphi中异步调用函数/过程(无组件),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1830594/

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