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处理总会滞后。

  • 相关阅读:
    CodeForces 734F Anton and School
    CodeForces 733F Drivers Dissatisfaction
    CodeForces 733C Epidemic in Monstropolis
    ZOJ 3498 Javabeans
    ZOJ 3497 Mistwald
    ZOJ 3495 Lego Bricks
    CodeForces 732F Tourist Reform
    CodeForces 732E Sockets
    CodeForces 731E Funny Game
    CodeForces 731D 80-th Level Archeology
  • 原文地址:https://www.cnblogs.com/chulia20002001/p/2037845.html
Copyright © 2011-2022 走看看