multithreading - Delphi:PostThreadMessage和PeekMessage不起作用

标签 multithreading delphi delphi-2009

当我的主应用程序(Delphi 2009)终止时,我希望它向我的线程(计时器,带有ADO Connections的TDataModules,SMTP等)发出信号,以进行优雅处理。

在我的主应用程序中,我具有以下内容:

try
      PostThreadMessage(bpvccMAILER.ThreadID, WM_SYSTEM_CLOSE, self.Handle, 0);
      returnMessage := (SysErrorMessage(GetLastError)); //Returns 'The operation completed successfully'
    while TRUE do
            begin
                sleep(1000);
                if not (Assigned(bpvccMAILER)) then
                begin
                    bpvccACTIVITY_LOGGER.Write('SHUTDOWN','TBPVCommunicatorGUI.FormClose - All Threads have shut down');
                    break;
                end;
                locWaited := locWaited  + 10;
            end;  
        except
        end;
    finally
        FreeAndNil(bpvccACTIVITY_LOGGER);
        FreeAndNil(bpvccMAILER);
    end;

线程类:
TBPVMailer = class(TThread)
    protected
        SMTP       : TIdSMTP;
        interval   : Integer;
        fMain      : Integer;
        fMainIsSvc : Boolean;
        fTerminated: Boolean;
        function SendEmail(AEmail: TEmailObj) : TBPVEmailSendResult;
        function doSleep : Boolean;
        procedure Write(AStatus, AMessage : String);
        procedure FlushQueue();
        procedure HandleMessage(var Message : TMessage); message WM_SYSTEM_CLOSE;
    public
        constructor Create(AServer : String; APort : Integer; AUser, APass : String; AInterval : Integer; StartSuspended : Boolean); overload;
        procedure   Execute; override;
        procedure QueueEmail(AEmail: TEmailObj; EmailType : TBPVEmailType; AssociatedID : String);
        destructor Destroy; override;
end;

procedure TBPVMailer.HandleMessage(var Message: TMessage);
var
msg : tagMSG;
begin
  PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
    fMain := Message.WParam;
    fMainIsSvc := Message.LParam = 1;
    fTerminated := TRUE;
end;

问题是,即使在调用PostThreadMessage之后,Assigned(bpvccMAILER)始终返回true。同样,bpvccMAILER.fTerminated始终为FALSE,这意味着从不执行TBPVMailer.HandleMessage,因为那是将值设置为TRUE的原因。我在做什么错,看来我的线程没有收到该消息?

最佳答案

明显的解释是您的线程中没有消息泵。您发布该消息,但线程不会泵送其队列。

该代码是不必要的复杂。似乎根本不需要消息。调用线程的Terminate方法,然后使用其WaitFor方法等待直到停止。甚至更简单,只需在线程上调用Free即可。

您的代码确实包含许多奇怪之处:

  • 为什么调用PeekMessage?我看不到那没有任何目的。
  • 应避免等待Sleep。您几乎总是可以使用专用的等待功能。
  • 奇怪的是,您等到bpvccMAILERnil,然后再使用FreeAndNil(bpvccMAILER)
  • 仅当定义明确时才必须调用GetLastError。通常,仅当前面的API调用失败时。 API调用返回的值指示失败。
  • 关于multithreading - Delphi:PostThreadMessage和PeekMessage不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21670162/

    相关文章:

    java - 如何在Java中的不同对象之间进行等待和通知?

    c++ - OpenMP 似乎没有并行运行

    windows - 在哪里可以找到有关 Windows 10 进程调度的详细信息?

    multithreading - 我的代码中的随机访问违规

    mysql - 基于数据库查询调用TEdit对象

    delphi - 如何在 TWebBrowser 中捕获页面区域?

    Delphi 2009 以错误的顺序创建我的组件

    delphi - 由于什么设计原因,TCanvas.StretchDraw 无法按 TIcon 的预期工作?

    delphi - TClientDataset - 是否可以按 unicode 列名称进行过滤?

    java - 同步以确保对不可变对象(immutable对象)的引用将被另一个线程看到