我在ACTIVEFORM中类名为XXX中,创建了一个线程类,该线程类是这样的
TMyThread = class(TTread)
......
proceduce    Execute;
......
XXX类中,我定义了  InDevThread : TMyThread;
创建该线程是这样的
...
begin
     InDevThread := TMyThread.Create();
     if InDevThread = nil then exit;
     IniDevThread.OnTerminate := TheadDone;  // 这是该线程结束后,回调用的函数,是XXX类中的函数(TheadDone)
end;
...
proceduce XXX.TheadDone
begin
    showmessage('TheadDone');
end;// 问题是,当线程结束时这个ThreadDone一直没有执行,有趣的是,当我点击了无关的按钮,而且按钮里面有
// 这句代码:showmessage('????'); 这是, ThreadDone竟然调用了,而且showmeage('ThreadDone');调用了
// 请问这是怎么回事
// 还是请注意我在 ACTIVEFORM中实现的,也就是控件中实现的, 在EXE中,那都是正确的。

解决方案 »

  1.   

    在非Exe当中尽可能不使用ShowMessage,换用MessageBox
      

  2.   

    线程结束后没触发回调函数吧。也极有可能是你回调函数里面有showmessage,而在线程中并没有引用showmessage所在单元
    所以其OnTerminate 事件时并没有运行到回调函数,而当你回到主线程,消息机制把刚才的回调函数消息发给主线程,主线程运行
    TheadDone 这个回调函数
      

  3.   

    proceduce XXX.TheadDone 
    begin 
       // showmessage('TheadDone'); // 这里的showmesage只是做测试
       // todo:
         .......// 代码
    end; 
    当我点击了无关的按钮,而且按钮里面有 
    // 这句代码:showmessage('????'); ,如果是messagebox()
    // 确实没有 showmessage的效果,
    // 如果在无关的按钮代码里换上 formtest。showmodal();效果跟showmessage();一样。 但是如果是formtest。show();就又没有效果了。
      

  4.   

    简洁的说就是在ACTIVEX 中的 主窗体类我创建的一个线程类,
    当线程正常结束后,  主窗体的线程结束回调函数无法响应。  只有当无关代码中
    出现了SHOWMESSAGE(‘’) 这句代码后, 主窗体的线程结束回调函数才响应了。
      

  5.   

    在非EXE当中不要使用类似的同步机制(包括Synchronize).原因在于非Delphi Exe需要附加在其它应用程序的进程当中,而此时Delphi Library所认为的主线程,即第一个加载该Library的线程,很有可能只是别人的一个子线程(这个并不是致关重要的),而Delphi的线程同步机制是Delphi子线程往一个同步队列当中增加一个事件的调用代码,然后Post一个消息,到所谓的主线程当中,然后自己就挂起,直到主线程(即第一个调用Library的线程),处理完对会唤.OnTerminate事件也是类似做法.而由于是附加到别人的线程当中,那么自己就没有MessageLoop,而别人的线程未必能够识别线程同步消息(WM_NULL),从而不会进入同步处理,直到自己的UI类得到消息处理的机会之后.
      

  6.   

    非常感谢6楼说的这么详细,
    感觉上也明白了,一些原理。 
    好像应该是 : 当作为ACTIVEX时里面的消息,并不是像主线程那样,是作为一个线程在跑,而且里面的消息机制,跟在主线程中也稍微不一样。是这个意思吧。明白是明白了一些。但是怎么解决,我这个问题呢?
    解决方案我也想到了一个,就是加个定时器,定时判断该线程是否结束,可我觉得,
    这个解决方案非常不好。所以想问下,有没有更好的解决方案。 就是想得到线程结束。进入我的回调函数中。
    谢谢!
      

  7.   

    如果不需要切换线程的话
    procedure myThread.Execute;
    begin
      try
        ...
      finally
        DoTerminateProc;
      end;
    end;