Seb*_*ian 9 delphi asynchronous callback
我试图在Delphi中异步运行一个函数或过程,但是没有使用组件,有没有办法用delphi核心函数做到这一点?
mgh*_*hie 17
如果你问的是VCL是否具有开箱即用的.NET中的BeginInvoke,那么答案就是否定的.但是,您可以通过链接到程序的小单元形式获得非常相似的东西,即Andreas Hausladen 的AsyncCalls库.它不是一个组件,所以我猜它有资格.它还支持从版本5开始的Delphi.非常推荐.
编辑:
我将添加一个示例,因为您没有运行它.如果你的调用代码被阻塞,那么你的问题是没有引用IAsyncCall
该函数返回的接口指针.因此,当临时引用超出范围时,将立即销毁实现该接口的对象.析构函数将在VCL线程的上下文中调用,它将调用WaitForSingleObject()
或类似函数等待工作线程完成.结果是你的VCL线程阻塞.
如果您保持对接口指针的引用,您将获得正确的行为:
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;
Run Code Online (Sandbox Code Playgroud)
将定时器设置为禁用,让它有一个非常短的Interval
,比如说50 ms.按钮单击启动异步操作:
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;
Run Code Online (Sandbox Code Playgroud)
当操作处于活动状态时,无法启动其他操作.完成后,它使计时器能够通知表单并重置接口引用:
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;
Run Code Online (Sandbox Code Playgroud)
注意如何使用EnterMainThread()
和直接从被调用的方法访问表单LeaveMainThread()
.
以上代码不是绝对最小值,仅用于展示一些想法.
您可能还想在线程上执行您的过程.然后使用OnTerminate事件来获取结果.是的,在.NET和C#的这些日子里,我们被某种简单易用的执行方法所破坏,但这就是它在Delphi上运行的方式.
归档时间: |
|
查看次数: |
13172 次 |
最近记录: |