zoukankan      html  css  js  c++  java
  • 线程与VCL的消息同步

    http://www.zzyubo.com/runsoft/article.asp?id=34

    Delphi实现多线程很简单,得益于TThread的良好封装。若在线程中使用VCL,例如要宣告一个事件,并在线程中触发它,一般的方法是使用Synchronize。
    在Project中这么用可能没什么,但在Dll中呢?例如在链接库中封有窗口,并在里面实现一个与滚动条界面打交道的线程。
    当 线程用Synchronize同步时,会被锁死,由此产生另外一种特效:移动鼠标,线程操作的滚动条就改变进度;否则进度条就不见动静。事实是线程被锁死 了,准确的说是Synchronize中WaitForSingleObject函数无法返回,它在等主进程处理完进度条后返回,但主进程似乎没有搭理 它。

    而且Synchronize还有一个缺点,就是除了要同步的过程外,无法传递其他参数。
    消息机制的同步,大体分三个部分:
    1.发送(由线程完成)
    2.接收(由主进程完成)
    3.处理(由主进程完成)

    可以看到,线程只要发送需要同步的数据(事件)就可以了,其它都是在主进程里完成的。
    实现:
    1.TZipThread = class(TThread)
    protected
    procedure DoProcessBar; //负责发送进度条数据
    end;

    2.TThreadEvent = class
    protected
    FHwnd: THandle; //消息句柄
    procedure DoProcessBar(nValue: Cardinal); //负责接收数据
    procedure WndProc(var nMsg: TMessage); //负责处理数据
    end;

    大致的框架就是这样,现在让它运行起来:
    1.
    TZipThread.DoProcessBar; //发送
    begin
    Event.DoProcessBar(55);
    end;

    2.
    TThreadEvent.DoProcessBar; //接收
    begin
    FBarValue := nValue;
    PostMessage(FHwnd, WM_MyData, 0, 0);
    end;

    3.
    TThreadEvent.WndProc(var nMsg: TMessage); //处理
    begin
    if nMsg.Msg = WM_MyDATA then ProcessBar1.Position := FBarValue;
    end;

    很简单吧,说白了就是在线程中维护一个消息队列,需要与VCL打交道时就发消息,至于VCL是否处理或是否处理完毕,那是别人的事,咱作线程的不管这个。

    那么,由此产生了两个问题:1.VCL处理的肯定没有线程快,那么后来的数据会覆盖先来的。2.对进度条而言,进度刚显示完10就一下子跳到100了。
    解决方法是:1.对于只触发一次的事件,使用变量缓存;对于多次触发的,使用TThreadList缓存成列表,然后在处理时依次对List操作。2.没办法解决。因为线程发出消息后不管,VCL处理总会滞后。

  • 相关阅读:
    关于如何使`(a === 1 && a === 2 && a === 3)`返回`true`问题的思考
    选择适合的类型判断方式
    this的指向问题
    MarkDown基础语法记录
    快速掌握vuex状态管理
    自己如何手动实现一个isNaN的方法
    移动端webapp使用flex布局解决底部导航被手机键盘顶起
    swiper文字内容超出一屏的时候如何实现区域滚动不翻页
    css3动画如何实现停止以后停留在最后一帧动画
    检测任意数据类型
  • 原文地址:https://www.cnblogs.com/chulia20002001/p/2037845.html
Copyright © 2011-2022 走看看