• 迥异和诡异的SendMessage和PostMessage


    1       故障现象

    故障现象1:能够收到SendMessage()发出的消息,但收不到PostMessage()发出的消息。

    故障现象2:能够收到PostMessage()发出的消息,但收不到SendMessage()发出的消息。

    2       两个比喻

    从发送端来说:

    SendMessage()好比电信系统提供通话服务。

    如果对方占线,立即返回。

    如果对方不占线,就保持呼叫→接收端接听→通话→挂断。在挂断之前,发送端处于阻塞状态,不可以干别的事。

    PostMessage()好比电子邮件系统提供电子邮件服务。

    发送端把邮件交给电子邮件系统,然后立即返回,就可以干别的事了。

    电子邮件系统将邮件放在队列缓存区中,缓慢地将邮件发送到接收端的邮箱里。

    从接收端来说(!!! 关键 关键 关键 !!!)

    要接收SendMessage()的消息,必须用手机接听,到邮箱里无法接收此类消息。

    要接收PostMessage()的消息,必须到邮箱里接收,用手机无法接听此类消息。

    1       技术原理

    在本文中:

    把SendMessage()发送的消息成为立即消息。

    把PostMessage()发送的消息成为延迟消息。

     

    在计算机系统里,立即消息和延迟消息分别使用完全不同的途径发送消息,必须采用相匹配的、完全不同的接收方法才能收到消息。

     

                           

    1.1      立即消息的收发

    为了接收并处理立即消息,接收端应用程序必须准备一张(消息,处理函数)映射表,如下表所示:

    消息

    处理函数

    WM_USER + 1

    OnWmUser_1

    WM_USER + 2

    OnWmUser_2

    WM_USER + n

    OnWmUser_n

    立即消息的发送与接收的协作流程如下表:

    发送端应用程序

    操作系统

    接收端应用程序

    (消息处理总入口函数)

    发送消息

    阻塞发送端应用程序

    调用接收端应用程序的消息处理总入口函数

    在(消息,处理函数)映射表中搜索与消息相匹配的处理函数,立即调用处理函数。

    向操作系统返回处理结果

    向发送端应用程序返回处理结果

    解除阻塞发送端应用程序

    接收消息处理结果

    继续其它事务

    1.2      延迟消息的收发

    延迟消息的发送与接收的协作流程如下表:

    发送端应用程序

    操作系统

    接收端应用程序

    发送消息

    将消息放入接收端应用程序的消息队列中

    继续其它事务

    从消息队列中取出消息慢慢处理。

    2       具体实现

    以C++ Builder为例。

    2.1      接收立即消息

    要接收立即消息,也就是由SendMessage()发送的消息。

    步骤1:声明并定义消息处理函数

    步骤2:声明和定义(消息,处理函数)映射表

    class TForm2 :   public TForm

    {

      // 声明WM_COPYDATA 消息的处理函数

      void __fastcall OnCopyData(const   TMessage &msg);

    // 受理立即消息 --- 由 SendMessage() 发送的消息

    // 声明和定义(消息,处理函数)映射表

    BEGIN_MESSAGE_MAP

      VCL_MESSAGE_HANDLER(WM_COPYDATA, TMessage, OnCopyData);

    END_MESSAGE_MAP(TForm)

    };

    2.2      接收延迟消息

    要接收延迟消息,也就是由PostMessage()发送的消息。

    放置一个TApplicationEvents控件,该控件只能接收延迟消息,无法接收立即消息。

    编写TApplicationEvents.OnMessage事件处理函数。如下表:

    void __fastcall   TForm2::AppEventsMessage(tagMSG &Msg, bool &Handled)

    {

      // 若收到延迟消息WM_USER_1

      if (Msg.message == WM_USER_1)

      {

        // 此处编写消息处理代码

        // 设立标志,消息已被处理

        Handled   = true;

      }

      else {

        // 设立标志,消息未被处理

    Handled = false;

      }

    }

    3       结论

    SendMessage()和PostMessage()的共性:

    都能发送消息。

    SendMessage和PostMessage的差异:

    采用完全不同的途径发送消息,也要采用完全不同的方法和途径接收消息。

    若接收途径与发送途径不匹配,就无法接收消息。

    通过SendMessage()发送的消息,发送端发送并必须等待接收端处理,接收端立即处理并向发送端反馈处理结果,无延迟。

    通过PostMessage()发送的消息,发送端发送后立即返回,不等待接收端不处理,接收端缓慢地延迟处理。

     

    SendMessage

    PostMessage()

    发送端

    直接发给接收端

    要求接收端立即处理

    在接收端处理完毕之前处于阻塞状态,不可以干别的事

    可以立即获悉接收端的处理结果

    消息经由OS缓存到接收端的消息队列里

    发送完毕立即返回,可以干别的事

    接收端

    立即处理收到的消息

    缓慢地从队列里取出消息并处理。

    4       其它

    SendMessage和PostMessage的其它特性,网上都有,本文不再重复与累述。

  • 相关阅读:
    aws亚马逊配置 https,操作步骤记录
    八年phper的高级工程师面试之路八年phper的高级工程师面试之路
    laravel 获取目录下的所有目录Storage::directories
    Docker 入门看这一篇就够了,万字详解!
    PHP 引用是个坑,请慎用
    php面试常问方法汇总
    注册、登录和 token 的安全之道
    分享一下最近的面试题,都是大厂
    Xpath2
    ActiveX控件的实现
  • 原文地址:https://www.cnblogs.com/micemik/p/11576878.html
Copyright © 2020-2023  润新知