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变量值是不是发生变化,如果发生变化,则退出循环,并终止线程是不是有另外一个方法,在线程开启时,可以知道这个线程的具有唯一性的东西(如句柄),请问怎么得到某个线程的句柄,又要怎么样根据句柄去终止线程呢??
我的线程定义如下:是定义在主单元中的一个线程类,没有新开单元。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变量值是不是发生变化,如果发生变化,则退出循环,并终止线程是不是有另外一个方法,在线程开启时,可以知道这个线程的具有唯一性的东西(如句柄),请问怎么得到某个线程的句柄,又要怎么样根据句柄去终止线程呢??
这是win32核准的做法,你可以用一个线程周期性检查一个event对象,通过这个对象来决定
在线程Excute的开始处加一个FreeOnTerminate:=true
然后在线程中的循环判断这个停止按钮的有效状态,如果btnStop.enabled = false
那么就退出循环。然后自动结束线程这样子做我没办法自由控制任一线程的停止与否只能全部一起控制。
这种结束,是用规则来约定的,不是强制结束线程。
Terminate 过程会设置线程的一个boolean变量FTerminated := True所以,你需要在线程的 Execute 中去主动判断这个变量的值(通过线程的 Terminated 属性进行判断)
通常情况下,Execute 的实现类似下面的样子while not Terminated do
begin
......
end; 当然,如果你在Execute 中不做这种判断,Terminate 过程也就不会有终止线程的作用。
所以说 Terminate 过程终止线程仅仅是用一个约定来实现的,如果你在实现线程的Execute中不遵守这个约定,他也就不能结束你的线程
调用 Terminate 过程的,可能是主线程,而执行Execute的却是在子线程中,这样就存在两个线程同时对一个变量FTerminated进行读写操作,这在单核心上,这种直接常量赋值可以看成是原子操作,但是在多核心下,就可能会出问题,可能一个核心在写这个变量的同时另一个核心在读这个变量但是,这个问题,其实也没什么,因为TThread本身就不是那种对线程结束操作非常敏感的类,最多是多执行一次while循环而已。
procedure Execute; override;
Public
constructor Create;
destructor Destroy; override;
end;最好Destroy自然结束,再在其他地方检查该线程对象是否存在
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;
所以說,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;所以執行線程仍然必須繼續執行到正常結束後才行,而不是立即終止執行線程,這一點要注意。
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;