- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试在 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/
我是一名优秀的程序员,十分优秀!