200分。怎么安全终止线程?
我的线程定义如下:是定义在主单元中的一个线程类,没有新开单元。
Type
  ThScan = class(TThread)
  protected
    procedure Execute; override;
    procedure Sync1;
    procedure Sync2;
    procedure Sync3;
  private
    Err : string;
    Hot,Compen : Boolean;
    ProfitRatio : Double;
    ThreadID,Profit : Integer;
    GameName, BuyAddress : string;
    GoodsAddressList : TStringList;
    GameInfo, ScanAddressT, ScanAddress5 : string;
  public
    constructor Create(aThreadID:Integer; aHot:Boolean; aCompen:Boolean; aProfit:Integer; aProfitRatio:Double);
end;开启线程时,用线程的create函数来决定线程要做什么样的事呢。。并且记下当前线程的ID(aThreadID),在我的线程主的过过程Execute中我是用来判断窗体类的threadID变量值是不是发生变化,如果发生变化,则退出循环,并终止线程是不是有另外一个方法,在线程开启时,可以知道这个线程的具有唯一性的东西(如句柄),请问怎么得到某个线程的句柄,又要怎么样根据句柄去终止线程呢??

解决方案 »

  1.   

    最安全的退出线程应该就是让它自己执行完毕。像你说的这种情况,不如把线程设置为FreeOnTerminate:=true,需要结束线程的时候用thread.Terminate, 在线程中的关键位置判断Terminated是否为true
      

  2.   

    也可以自己定义一个标记,如bFlag,再你的Excute中的循环中不断的判断此标记,当你想结束线程时先更改bFlag的值,待Excute执行结束(瞬间),这时结束就行了。
      

  3.   

    一般情况是自己定义一个标记,利用这个标记的值来确定是否要求线程结束自己
    这是win32核准的做法,你可以用一个线程周期性检查一个event对象,通过这个对象来决定
      

  4.   

    我现在的做法是在主单元中做一个标记。如停止按钮的有效状态。
    在线程Excute的开始处加一个FreeOnTerminate:=true
    然后在线程中的循环判断这个停止按钮的有效状态,如果btnStop.enabled = false 
    那么就退出循环。然后自动结束线程这样子做我没办法自由控制任一线程的停止与否只能全部一起控制。
      

  5.   

    如果你使用delphi的线程类TThread,那么,每一个线程类都有一个 Terminate 过程,这个过称用来结束当前线程。
    这种结束,是用规则来约定的,不是强制结束线程。
    Terminate 过程会设置线程的一个boolean变量FTerminated := True所以,你需要在线程的 Execute 中去主动判断这个变量的值(通过线程的 Terminated 属性进行判断)
    通常情况下,Execute 的实现类似下面的样子while not Terminated do
    begin
      ......
    end; 当然,如果你在Execute 中不做这种判断,Terminate 过程也就不会有终止线程的作用。
    所以说 Terminate 过程终止线程仅仅是用一个约定来实现的,如果你在实现线程的Execute中不遵守这个约定,他也就不能结束你的线程
      

  6.   

    如果你想在任意时候立刻终止线程,那么,还是用api来创建线程吧,delphi提供的线程类,不适合这种需求,如果你强制终止了TThread创建的线程,那么在TThread析构的时候可能会报错。另外,delphi的线程类TThread的  Terminate 方式终止线程,可能会存在一些问题,因为在多核心的处理器下, 直接采用 FTerminated := True;的方式,可能会导致你在Execute 中对 while not Terminated do的判断出现问题
    调用 Terminate 过程的,可能是主线程,而执行Execute的却是在子线程中,这样就存在两个线程同时对一个变量FTerminated进行读写操作,这在单核心上,这种直接常量赋值可以看成是原子操作,但是在多核心下,就可能会出问题,可能一个核心在写这个变量的同时另一个核心在读这个变量但是,这个问题,其实也没什么,因为TThread本身就不是那种对线程结束操作非常敏感的类,最多是多执行一次while循环而已。
      

  7.   

    设定一个布尔类型的标志变量,当线程正在执行功能时,设置该变量为True,此时不允许终止,当没有执行功能时,设置为False,此时可以终止线程。
      

  8.   

      protected
        procedure Execute; override;
      Public
        constructor Create;
        destructor Destroy; override;
      end;最好Destroy自然结束,再在其他地方检查该线程对象是否存在
      

  9.   

    在Execute中,检测Terminated的值。
    procedure Execute;
    begin
        FTerminated := True;
        ...
        ...
        if Terminated then exit; 
        ...
        if Terminated then exit;
        ...
        if Terminated then exit;
        ...
        if Terminated then exit;
        ...
    end;
    终止线程调用Terminate过程。调用此过程后,线程不是立刻结束。Terminated由false变成ture。
    当执行的你的任意一个Terminated 判断后,从Execute中跳出。之后此线程结束。如果需要在线程结束后,自动释放内容需要在Execute中加入FTerminated := True;
      

  10.   

    設置執行線程類的Terminated標誌...首先判斷執行線程類的Terminated標誌,如果未被標誌為終止,則調用執行線程類的Execute方法執行執行線程代碼,因為TThread是抽象類別,Execute方法是抽象方法,所以本質上是執行派生類中的Execute代碼。
        所以說,Execute就是執行線程類中的執行線程函數,所有在Execute中的代碼都需要當作執行線程代碼來考慮,如防止訪問衝突等。
        如果Execute發生異常,則通過AcquireExceptionObject取得異常物件,並存入執行線程類的FFatalException成員中。
        最後是執行線程結束前做的一些收尾工作。區域變數FreeThread記錄了執行線程類的FreeOnTerminated屬性的設置,然後將執行線程返回值設置為執行線程類的返回值屬性的值。然後執行執行線程類的DoTerminate方法。
    DoTerminate方法的代碼如下:procedure TThread.DoTerminate;
    begin
      if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
    end;    很簡單,就是通過Synchronize來調用CallOnTerminate方法,而CallOnTerminate方法的代碼如下,就是簡單地調用OnTerminate事件:procedure TThread.CallOnTerminate;
    begin
      if Assigned(FOnTerminate) then FOnTerminate(Self);
    end;    因為OnTerminate事件是在Synchronize中執行的,所以本質上它並不是執行線程代碼,而是主執行線程代碼(具體見後面對Synchronize的分析)。
        執行完OnTerminate後,將執行線程類的FFinished標誌設置為True。
        接下來執行SignalSyncEvent過程,其代碼如下:procedure SignalSyncEvent;
    begin
      SetEvent(SyncEvent);
    end;    也很簡單,就是設置一下一個全域Event:SyncEvent,關於Event的使用,本文將在後文詳述,而SyncEvent的用途將在WaitFor過程中說明。
        然後根據FreeThread中保存的FreeOnTerminate設置決定是否釋放執行線程類,在執行線程類釋放時,還有一些些操作,詳見接下來的析構函數實現。
        最後調用EndThread結束執行線程,返回執行線程返回值。
        至此,執行線程完全結束。
        說完構造函數,再來看析構函數:destructor TThread.Destroy;
    begin
      if (FThreadID <> 0) and not FFinished then
      begin
        Terminate;
        if FCreateSuspended then
          Resume;
        WaitFor;
      end;
      if FHandle <> 0 then CloseHandle(FHandle);
      inherited Destroy;
      FFatalException.Free;
      RemoveThread;
    end;    在執行線程物件被釋放前,首先要檢查執行線程是否還在執行中,如果執行線程還在執行中(執行線程ID不為0,並且執行線程結束標誌未設置),則調用Terminate過程結束執行線程。Terminate過程只是簡單地設置執行線程類的Terminated標誌,如下面的代碼:procedure TThread.Terminate;
    begin
      FTerminated := True;
    end;所以執行線程仍然必須繼續執行到正常結束後才行,而不是立即終止執行線程,這一點要注意。
      

  11.   

    扫描网站一般都要进行Socket连接,你把Socket关掉,然后让等待Socket的函数返回来结束线程。线程最安全最标准的做法是设置FTerminated和检测FTerminated来退出。
      

  12.   

    主程序里:
     var
      thread1,thread2,thread3:TMonitorThread;//线程变量要多少就定义多少个,定义成全局的,实际应用你最好做成线程池,现只是简单举例,TMonitorThread为一个线程类
    ......
      thread1:=TMonitorThread.Create(false);//这就开始了
      thread2:=TMonitorThread.Create(false);//这就开始了
      thread3:=TMonitorThread.Create(false);//这就开始了 //想停止?
     if (thread2<>nil) and (想停止的条件) then
       thread2.Terminate;//停止,因为TMonitorThread里设了FreeOnTerminate:=True;就不需要在去Free了TMonitorThread的定义:最好是New->Thread Objects来建立type
      TMonitorThread= class(TThread)
      private
       
      protected
       
      procedure Execute; override;
      end;
    implementation.....
    procedure TMonitorThread.Execute;
    begin
     { Place thread code here }
     inherited;
        FreeOnTerminate:=True;
      ....
     try
        CoInitialize(nil);
        while not terminated do
          begin
          ....
          Sleep(10);
          end;
     finally
          CoUnInitialize;
        end;
    end;