在 Delphi 中使用线程 线程,当窗体关闭 关闭时,如果窗体中启用了线程 线程,一般需要手动 线程 关闭 线程 关闭,以释放资源。 关闭 常用来结束线程 线程的代码为: 线程 PcmThrd.Terminate; PcmThrd.WaitFor; 即先触发 Terminate 方法,然后等待线程 线程的结束。 线程 这种方法要求线程 线程不能使用 FreeOnTerminate := True; ,否则在 WaitFor 即将 线程 结束的时候会引发“无效句柄”的错误。 这种方法在窗体关闭 关闭的时候会等待一段事件(因为 WaitFor)。 关闭 因此,如果不是在主窗体中结束线程 线程时,其实我们可以不必使用 WaitFor。而是 线程 采用如下方法: 将 FreeOnTerminate := True; 这样在窗体关闭 关闭的代码中直接调用 关闭 PcmThrd.Terminate; 即可。 注意: 如果设置了 PcmThrd.OnTerminate := SomeFunction; 那么在调用 PcmThrd.Terminate;前尽量将 PcmThrd.OnTerminate := nil,以免 结束线程 SomeFunction 中的变量出现空指针错误。当然,这不是绝对的,需 线程后 线程 要根据具体程序而定 DELPHI 线程的终止和退出 1)自动退出: 一个线程从 execute()过程中退出,即意味着线程的终止,此时将调用 windows 的 exitthread()函数来清除线程所占用的堆栈。 如果线程对象的 freeonterminate 属性设为 true,则线程对象将自动删除,并释放线 程所占用的资源。 这是消除线程对象最简单的办法。 2)受控退出: 利用线程对象的 terminate 属性,可以由进程或者由其他线程控制线程的退出。只需 要简单的调用该线程的 terminate 方法,并设直线程对象的 terminate 属性为 true。 在线程中, 应该不断监视 terminate 的值, 一旦发现为 true, 则退出, 例如在 execute() 过程中可以这样写: while not terminated do begin ........ end; 3)退出的 api 函数: 关于线程退出的 api 函数声明如下:code function terminatethread(hthread:thandle;dwexitcode:dword); 不过,这个函数会使代码立刻终止,而不管程序中有没有 try....finally 机制,可能会导致错误,不到万不得已,最好不要使用。 4) 利用挂起线程的方法(suspend) 利用挂起线程的 suspend 方法,后面跟个 free,也可以释放线程,例如: thread1.suspend; thread2.free; //挂起 //释放 遇到的" 的问题 遇到的 Code:1400 无效窗口句柄 "的问题,关闭不了程序 的问 最近写程序,遇到的" Code:1400 无效窗口句柄 "的问题,关闭不了程序?! 似乎是在线程里调用了主窗体的东西,使得释放的先后次序被打乱了,所以句柄 有问题! 但是要找到问题的根源太麻烦了,这时有招必杀技! 大家要记好了,有类似的无法关闭程序的问题,一句搞定! ExitProcess(0); 简单的说就是终止自己的进程!虽然是暴力了一点,但是绝对有效! 但是这种方法不会触发 onclose 之类的事件,可以说是不触发任何事件,无痛无 痒地结束了进程,干净利落,所以要记得在结束之前保存必要的数据,做必要的 操作, 最好是释放一下内存, 会有内存残留。 最好是释放一下内存 在 Win 下结束进程是非常不干净的, 获取线程状态 Function CheckThreadFreed(aThread: TThread): Byte; var i: DWord; IsQuit: Boolean; begin if Assigned(aThread) then begin IsQuit := GetExitCodeThread(aThread.Handle, i); if IsQuit then //If the function succeeds, the return value is nonzero. //If the function fails, the return value is zero. begin if i = STILL_ACTIVE then //If the specified thread has not terminated, //the termination status returned is STILL_ACTIVE. Result := 1 else Result := 2; //aThread 未 Free,因为 Tthread.Destroy 中有执行语句 end else Result := 0; //可以用 GetLastError 取得错误代码 end else Result := 3; end; 快速关闭线程 //=========ThrdMain.pas================== Var hEventDead:Thandle; constructor ThrdMain.Create; begin hEventDead := CreateEvent(0,true,False,‘SMSdesktop‘);//创建对象事件 inherited Create(False); end; //创建对象关闭事件 function ThrdMain.WaitEventDead: Boolean; begin //创建线程 var Thread_Main:ThrdMain ;(调用自我创建的线程对象) Thread_Main:=ThrdMain.Create ; //关闭线程 Thread_Main.WaitEventDead ; Thread_Main.WaitFor ; //=========ThrdMain.pas================== var hEventDead:Thandle; constructor ThrdMain.Create; begin hEventDead := CreateEvent(0,true,False,‘SMSdesktop‘);//创建对象事件 inherited Create(False); end; //创建对象关闭事件 function ThrdMain.WaitEventDead: Boolean; begin Gbl_ReadSMS:=False; WaitForSingleObject(hEventDead,500);//表示在 0.5 秒内强制关闭 end; 多线程的检查,与关闭线程 多线程的检查 与关闭线程 procedure TDemoThread.Execute; begin inherited; if Assigned(FOnHintText) then FOnHintText(Self); end; procedure TForm1.ShowThreadDemo(Sender: TObject); var i: Integer; begin for i := 0 to 1000 do begin Memo1.Lines.Add(IntToStr(i)); end; end; procedure TForm1.Button2Click(Sender: TObject); var vI: DWord; IsQuit: Boolean; begin Demo := TDemoThread.Create(True); //True:创建时不启动线程 Demo.FreeOnTerminate := True; //设置程结束时自动释放 Demo.FOnHintText := ShowThreadDemo; //Demo.OnTerminate:= ShowThreadDemo; Demo.Resume; //启劫线程 end; procedure TForm1.FormDestroy(Sender: TObject); var vI: DWord; IsQuit: Boolean; begin if Demo <> nil then begin vi := CheckThreadFreed(Demo); //检查当前线程是否在执行 if (vi = 1) or (vi = 2) then TerminateThread(Demo.Handle, vi); //如果线程在执行则强行退出 Demo.Free; end; {if Demo<> nil then begin Demo.Terminate ; Demo.WaitFor ; end;} //等待线程结束,并终止它 end; procedure TForm1.Button1Click(Sender: TObject); begin Demo.Free; end; procedure TForm1.Button4Click(Sender: TObject); var vI: DWord; IsQuit: Boolean; begin //判断当前线程的状态 vI := CheckThreadFreed(Demo); ShowMessage(IntToStr(vI)); end;