首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >队列过程调用同一个[主]线程

队列过程调用同一个[主]线程
EN

Stack Overflow用户
提问于 2016-08-17 13:00:30
回答 3查看 794关注 0票数 5

我正在处理一些特定的TForm事件CMControlListChanging,,需要修改该(插入)控件,但是当我尝试这样做时,事情会变得很糟糕,因为显然它并不打算在VCL操作的中间中这样做。

因此,我需要将控制修改的CMControlListChanging延迟到,通过queuing将代码从处理程序中移开,以便在稍后的时间调用。

当然,我可以做PostMessage的事情,但是我想要更通用的方法。

System.Classes单元

类过程同步(ASyncRec: PSynchronizeRecord;QueueEvent: Boolean = False);重载;

它可以完成这个任务,但是它会检查CurrentThread.ThreadID = MainThreadID,如果是,则调用方法我会立即排队。

延迟调用的好方法,至少在主线程上是这样的吗?

EN

回答 3

Stack Overflow用户

发布于 2016-08-17 13:47:49

不确定这是否是您想要的,但是如果您使用的是最近的Delphi版本,这些延迟方法可能会派上用场。在应用了可选的非阻塞延迟后,它们在主线程中执行AProc。

代码语言:javascript
复制
uses
  System.Threading,
  System.Classes;

procedure Postpone(AProc: TThreadProcedure; ADelayMS: Cardinal = 0); overload;
begin
  TTask.Run(
    procedure
    begin
      if ADelayMS > 0 then begin
        TThread.Sleep(ADelayMS);
      end;
      TThread.Queue(nil, AProc);
    end);
end;

procedure Postpone(AProc: TThreadMethod; ADelayMS: Cardinal = 0); overload;
begin
  TTask.Run(
    procedure
    begin
      if ADelayMS > 0 then begin
        TThread.Sleep(ADelayMS);
      end;
      TThread.Queue(nil, AProc);
    end);
end;
票数 4
EN

Stack Overflow用户

发布于 2018-09-13 09:10:59

这个怎么样?它不创建新任务,只创建一个新的HWND (接收消息):

代码语言:javascript
复制
TYPE TDelayedProc = REFERENCE TO PROCEDURE;

TYPE
  TPostponeClass        = CLASS(TWinControl)
                            CONSTRUCTOR Create(P : TDelayedProc);
                          STRICT PRIVATE
                            Proc        : TDelayedProc;
                            PROCEDURE   Run(VAR M : TMessage); MESSAGE WM_USER;
                          END;

CONSTRUCTOR TPostponeClass.Create(P : TDelayedProc);
  BEGIN
    INHERITED Create(NIL);
    Parent:=Application.MainForm;
    Proc:=P;
    PostMessage(Handle,WM_USER,0,0)
  END;

PROCEDURE TPostponeClass.Run(VAR M : TMessage);
  BEGIN
    Proc;
    Free
  END;

PROCEDURE Postpone(Proc : TDelayedProc);
  BEGIN
    TPostponeClass.Create(Proc)
  END;

它甚至适用于匿名方法,因此您可以推迟执行事件的一部分,并且仍然可以访问局部变量(以及实例"Self")。

像这样使用它:

代码语言:javascript
复制
PROCEDURE WriteFile(CONST F : TFileName ; CONST STR : STRING);
  VAR
    TXT : TextFile;

  BEGIN
    AssignFile(TXT,F);
    IF FileExists(F) THEN APPEND(TXT) ELSE REWRITE(TXT);
    WRITELN(TXT,STR);
    CloseFile(TXT)
  END;

PROCEDURE TForm37.Button1Click(Sender: TObject);
  CONST
    N       = 'LOGFILE.TXT';

  VAR
    LocalVar : INTEGER;

  BEGIN
    DeleteFile(N);
    LocalVar:=20;
    Postpone(PROCEDURE
               BEGIN
                 WriteFile(N,'Postponed Code: '+Name+' ('+IntToStr(LocalVar)+')')
               END);
    WriteFile(N,'Last statement in event: '+Name)
  END;

LOGFILE.TXT文件将包含以下两行:

代码语言:javascript
复制
Last statement in event: Form37
Postponed Code: Form37 (20)

为了说明延迟的事件只在事件结束时运行,以及对局部变量的访问。

注意:在延迟调用和事件退出之间运行Application.ProcessMessages吗?如果运行,延迟的代码将在此时运行。

票数 0
EN

Stack Overflow用户

发布于 2018-09-13 10:24:44

从Delphi10.2东京开始,就可以使用TThread方法异步地推迟主线程的调用。

请参阅TThread.ForceQueue

类过程ForceQueue(const AThread: TThread;const AMethod: TThreadMethod);重载;静态;类过程ForceQueue(const AThread: TThread;const AThreadProc: TThreadProcedure);重载;静态; 在主线程中对方法调用的执行进行队列。 与队列不同,AMethod指定的方法调用的执行被强制排队,尽管它是由主线程调用的。 AMethod将调用线程关联起来:

  • 对于静态方法,可以使用AMethod参数将AThread与任何线程关联。
  • 如果不需要知道主线程中调用线程的信息,可以使用nil/NULL作为AThread参数。
  • RemoveQueuedEvents使用这些线程信息来查找正确的排队方法。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38997386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档