窗体Form1在ShowModal时启动一个定时器,让定时器在稍后创建一个子线程Thread1,该线程负责在后台处理数据。当Thread1处理完数据之后,会通知窗体Form1,让它从ShowModal死等状态中出来,使程序继续往后运行:
Synchronize(
    procedure
    begin
      Form1.ModalResult := mrOK;
    end
  );现在的问题是,时不时会发生子线程Thread1给Form1发送mrOK消息之后,Form1仍然停留在ShowModal状态死等的情况,好像Form1没有收到消息的样子。查了一下相关资料,说是“Form1.ModalResult := mrOK;”相当于PostMessage,只负责把消息成功发送出去就马上返回,不管对方有没有接收到。如何解决这个问题?感觉现在采用的同步机制很不可靠。
或者有其他更好的方法可以使用?

解决方案 »

  1.   

    弄一个公共变量,子线程修改,Form检查后再执行之后代码。
      

  2.   

    线程生命周期归谁管?子线程何时结束?Synchronize(
        procedure
        begin
          Form1.ModalResult := mrOK;
        end
      );如果为Form1管,这种代码意味着,可能会发生form1释放后,子线程还在跑。
    另要确保timer只创建一个线程。
      

  3.   


    线程Thread1的生命周期归Form1管。该线程在Execute的最后(即声明周期快结束时)才用Synchronize来同步Form1.ModalResult的,另外Form1在ShowModal之后,还会继续处理其他一些事情,这就确保了在Form1释放之前,其子线程Thread1已经被释放。所以,你的担心不存在。
    现在要解决的问题,子线程已经结束了,但Form1仍然处于ShowModal死等状态。
      

  4.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;const
        WM_THREADEND = WM_USER + 1;type
      TForm1 = class(TForm)
        btn1: TButton;
        procedure btn1Click(Sender: TObject);
      private
        procedure OnThreadEnd(var msg: TMessage); message WM_THREADEND;
        { Private declarations }
      public
        { Public declarations }
      end;  TTestThread = class(TThread)
      private
        FOwner: TObject;
      protected
        procedure Execute(); override;
      public
        constructor Create(const owner: TObject);
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.btn1Click(Sender: TObject);
    var
      f: TForm1;
    begin
      f := TForm1.Create(nil);
      TTestThread.Create(f);
      f.ShowModal;
    end;procedure TForm1.OnThreadEnd(var msg: TMessage);
    begin
      Self.Close;
    end;{ TTestThread }constructor TTestThread.Create(const owner: TObject);
    begin
      FOwner := owner;
      inherited Create(False);
    end;procedure TTestThread.Execute;
    begin
      Sleep(5000);
      SendMessage((FOwner as TForm).Handle, WM_THREADEND, 0, 0);
    end;
    end.自己消息处理试试。
      

  5.   

    我担心的问题,考虑CPU线程调度因素,可能会出现那种状况建议子线程用PostThreadMessage方式,通知主线程处理。
    form1最好能检测线程是否结束,并做相应处理。