偶在DLL里面用线程的时候出的问题,有人能帮忙解决吗,下面是主要的代码.//这个是线程unit CheckThread;interfaceuses
  Classes {$IFDEF MSWINDOWS} , Windows {$ENDIF};type
  MyThread = class(TThread)
  public
    constructor Create(ClassNum:integer);
  private
    ClassNum:integer;
    LastRes:integer;
    Ready:boolean;
    procedure Init;
  protected
    procedure Execute; override;
  end;implementationprocedure MyThread.Execute;
begin
  while not(Terminated) do
  begin
  Suspend;  Ready:=true;
  end;
  inherited;
end;constructor MyThread.Create(ClassNum:integer);
begin
  inherited Create(false);
  self.ClassNum:=ClassNum;
  Init;
end;procedure MyThread.Init;
begin
  LastRes:=0;
  Ready:=false;
end;end.由于种种原因,DLL里面是这样用线程的
//DLL的部分代码,实际执行的部分。
library xxx;var
    Thread:MyThread;
    SaveDllProc:TDLLProc;......
......procedure LibExit(Reason: DWord);
begin
  if Reason = DLL_PROCESS_DETACH then
  begin
    if Thread <> nil then
    begin
      Thread.Terminate;
      if Thread.Suspended then Thread.Resume;
      Freeandnil(Thread);
    end;
  end;
//  SaveDllProc(Reason);  // call saved entry point procedure
end;exports 
   ..............begin
  Thread := MyThread.Create(4);
  SaveDllProc := DllProc;
  DllProc := @LibExit;  // install LibExit exit procedure
  LibExit(DLL_PROCESS_ATTACH);
  Randomize;
end.希望是 程序在DLL载入时加载线程但不启动Execute。(正常)
       DLL卸载时关闭线程(可能是运行的也可能是Suspened)。(程序挂起)问题有2个
1、如果加上SaveDllProc(Reason),就是去掉的那行,则系统将在运行到该行时报错。
2、如果加载Dll,然后卸载掉,会停在Freeandnil(Thread);线程没有Exit,
如果在Freeandnil(Thread)前面加上Thread.WaitFor;那么,就会停在Waitfor处,第一个问题不是很重要。
第2个问题很关键,我在调试的时候有时可以正常Exit线程,但大多数时候就不能。
我一直希望了解如果是在挂起(Suspended)的状态下,使线程正常关闭的正确手法是什么。本人使用的环境是 Delphi 2005 (9.0.1761.24408), 使用 Delphi For Win32 , WindowsXP SP2.

解决方案 »

  1.   

    个人测试发现,问题主要出在Terminate这个线程的过程发生在DLL的DLL_PROCESS_DETACH中间,这样的话,线程退出时所触发的DLL_THREAD_DETACH时,程序流程尚在该函数体中未返回。
    我现在取消掉Freeandnil(Thread)以后DLL退出时会自动Exit线程。(按道理Delphi的内存管理会处理掉这个Thread对象,但个人无法保证这个过程)
    不过不知道这么做会不会有什么问题。如果确实问题是如我上面说言,那么就可以理解为什么加了WaitFor或者Free(Destory里面含WaitFor)会等待了,因为WaitFor必须等待线程结束的返回事件,于是结束进程的响应过程和正在等待的函数体相冲突,于是就产生了死锁。个人验证,正确的Free的过程确实如上面所述。
    下面是验证代码,有兴趣的自己调试一下
    //Unit1.pas
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, CheckThread;type
      TForm1 = class(TForm)
        procedure FormDblClick(Sender: TObject);
      private
        { Private declarations }
      public
        Test:MyThread;
        i:boolean;
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormDblClick(Sender: TObject);
    begin
      i:=not i;
      case i of
      true: Test :=MyThread.Create(3,false);
      false: begin
          Test.Terminate;
          Test.Resume;
          Test.WaitFor;
          Test.Free;
        end;
      end;
    end;end.
      

  2.   

    请高手看看如果在DLL里面不Free线程对象,会不会算个漏洞?
    如果必须Free,最好怎么做?