• 线程与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处理总会滞后。

  • 相关阅读:
    bzoj 2142 礼物——扩展lucas模板
    bzoj 4591 [Shoi2015]超能粒子炮·改——组合数前缀和
    bzoj 4403 序列统计——转化成组合数的思路
    bzoj 2982 combination——lucas模板
    bzoj 3505 [Cqoi2014]数三角形——排列组合
    bzoj 3398 [Usaco2009 Feb]Bullcow 牡牛和牝牛——前缀和优化dp / 排列组合
    bzoj 1009 [HNOI2008]GT考试——kmp+矩阵优化dp
    bzoj 2427 [HAOI2010]软件安装
    bzoj 1951 [Sdoi2010]古代猪文 ——数学综合
    bzoj4247挂饰——DP
  • 原文地址:https://www.cnblogs.com/chulia20002001/p/2037845.html
Copyright © 2020-2023  润新知