本帖最后由 ljdzxx 于 2011-03-08 13:31:54 编辑

解决方案 »

  1.   

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      CloseHandle(hTimerEvent);
    end;
      

  2.   

    execute代码里加上FreeOnTerminate := True;
      

  3.   

    从你的代码中看,如果你直接
    CloseHandle(hTimerEvent)
    则你的线程就会进入死循环
    做如下更改:
      case WaitForSingleObject(hTimerEvent,INFINITE) of
        WAIT_OBJECT_0: ;//干活;
        WAIT_TIMEOUT, WAIT_FAILED: Break;
      end;这样你
    CloseHandle(hTimerEvent)
    就会正常退出
      

  4.   

    试了还是不行,我知道什么原因了:我把CloseHandle放在线程的析构函数中执行,这样当我的主程序Free所有线程的时候就会执行了,但问题关键是:CloseHandle函数如果在调用WaitForSingleObject之前执行,那么WaitForSingleObject是会立即返回WAIT_FAILED的,可以正常退出,但现实情况是:N多线程都已经执行到WaitForSingleObject这句了并被这句代码阻塞,那么你再CloseHandle是无济于事的,WaitForSingleObject函数不会立即返回WAIT_FAILED,而是仍然要等够了设定的时间,才返回WAIT_OBJECT_0
      

  5.   

    说错了,我把CloseHandle放在“主窗体”的析构函数中执行,不是线程procedure TForm1.Destroy;
    beginCloseHandle(hTimerEvent);
    FreeAllThread;  //逐个释放所有线程end;
      

  6.   

    TThread的析构函数我看了,他先要检查线程中的工作是否已完成,没有完成的话要继续等它做完,然后才逐步释放资源。
      

  7.   


    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls;type
      TMyThread = class(TThread)
        FSite: integer;
      protected
        procedure Execute; override;
      public
        Constructor Create(CreateSuspended: Boolean);
        property Site : integer read FSite write FSite;
      end;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        t: integer;
      end;var
      Form1: TForm1;implementation{$R *.dfm}var
      hTimerEvent: THandle;  lpDueTime: Int64;        //ÑÓ³Ù
      lPeriod: Integer;        //ÖÜÆÚ
      lpTimerName: PChar;constructor TMyThread.Create(CreateSuspended: Boolean);
    begin
      inherited Create(true);
    end;procedure TMyThread.Execute;
    var
      i: Integer;
    begin
      FreeOnTerminate := True;
      for i := 0 to 500000 do
      begin
      if WaitForSingleObject(hTimerEvent, INFINITE) = WAIT_OBJECT_0 then
      begin
        Form1.Canvas.Lock;
        Form1.Canvas.TextOut(10, FSite*20, IntToStr(i));
        Form1.Canvas.Unlock;
      end;
      end;
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      t:= 1;
      lpTimerName := PChar('Knowing'+IntToStr(Handle));     //¶¨Ê±Äں˶ÔÏóÃû
      lPeriod := 100;              //ÖÜÆÚ
      lpDueTime := 0-1*100*10000;  //0-lPeriod*10000;//¸ºÊýΪÏà¶Ôʱ¼ä:¶¨Ê±Æ÷ºÎʱ¿ªÊ¼ÓÐÐźţ¬Õâ¸ö²ÎÊýÄܾ«È·µ½100ÄÉÃë
      hTimerEvent := CreateWaitableTimer(nil, False, lpTimerName);    //µÚ¶þ¸ö²ÎÊýΪÊÇ·ñÊÖ¶¯ÖØÖÃ
      SetWaitableTimer(hTimerEvent, lpDueTime, lPeriod, nil, nil, False);
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      mt: TMyThread;
    begin
      mt:= TMyThread.Create(true);      //  多按几次 button
      mt.FSite:= t;
      mt.Resume;
      inc(t);
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
      CloseHandle(hTimerEvent);
    end;end.
      

  8.   

    你的lPeriod := 100; 100是毫秒,设置过短测试不到效果的,你设置60秒试试,肯定要等N久才会退出!
      

  9.   

    我已经解决了,方法是窗体析构的时候,重新执行SetWaitableTimer,并设置一个极短的时间。
      

  10.   

    忘说了,你并没有在主程序退出的时候手动去释放这些线程,而是在线程里设置FreeOnTerminate := True;,你是想让线程自己释放,这样会有个问题:当你的主程序还没释放的时候这样做是没问题的,一旦你的主程序都退出了,如果你的线程里还有工作没昨晚,那你就惨了,你的线程在内存里会像没主人的孩子那样乱搞,一不小心就报Read Address 0x0000000XX 错误。