解决方案 »
- 买本本
- 如何给dbgrid加入序号列
- 大家进来看一下,谢谢,一分钟就好!!
- AdjustTokenPrivileges这个函数起什么作用?还请专家指点!
- 请高手指教
- 关于xpmnu
- 一个简单的关于table的操作?
- 请问ADO的时候用dateset执行update的时候,提示我update没有返回植,不能执行,请问如何解决?(62分献给大家)
- 菜鸟的困惑-急、急、急:PageControl中怎样放窗体?(我只有这些分了)
- 请教:如何能禁止显示数据库程序中BDE的用户登录对话框?
- 如何用delphi写一个在进程看不到的程序
- 谁来谈谈delphi里的过程类型及方法指针,并举几个实际应用的小例子???
threada[i].WaitFor;
threada[i].Free;
threada[i] := nil;
begin
if assigned(threada[i]) then
begin
threada[i].Terminate;
threada[i].WaitFor;
FreeAndNil(threada[i]);
end;
end
你可以再创建个线程,使用waitfor的方式等待所有的线程结束(结束的方式用你说的就可以,但是前提是你的线程函数中有对线程的 Terminated 变量进行判断才行)
所有线程结束之后,你创建的这个线程采用通知的方式通知主线程(比如使用sendmessage或者线程同步函数)
用一个等待线程,使用WaitForMultipleObjects函数进行等待
(程序中包括等待线程和测试线程)type
TThreadArray = array of TThread; TForm1 = class(TForm)
btnThreadStop: TButton;
btnThreadStart: TButton;
procedure btnThreadStopClick(Sender: TObject);
procedure btnThreadStartClick(Sender: TObject);
private
FThreads: TThreadArray; procedure AllOver(Sender: TObject);
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}type
TTestThread = class(TThread)
protected
procedure Execute; override;
end; TWaitThread = class(TThread)
private
FTA: TThreadArray;
FOnAllOver: TNotifyEvent;
procedure doAllOver();
protected
procedure Execute; override;
public
property OnAllOver: TNotifyEvent read FOnAllOver write FOnAllOver;
property TA: TThreadArray read FTA write FTA;
end;{ TTestThread }procedure TTestThread.Execute;
begin
while not Terminated do
WaitForSingleObject(Self.Handle, 500);
end;
{ TWaitThread }procedure TWaitThread.doAllOver;
begin
if Assigned(FOnAllOver) then FOnAllOver(Self);
end;procedure TWaitThread.Execute;
var
I, N, K: Integer;
hWait: array of THandle;
begin
N := High(FTA) - Low(FTA) + 1;
SetLength(hWait, N);
for I := Low(FTA) to High(FTA) do
begin
hWait[I] := FTA[I].Handle;
FTA[I].Terminate; if Terminated then Exit;
end;
I := N div 64;
K := N mod 64;
while I > 0 do
begin
WaitForMultipleObjects(64, @hWait[(I - 1) * 64], True, INFINITE);
Dec(I); if Terminated then Exit;
end;
WaitForMultipleObjects(K, @hWait[I * 64], True, INFINITE);
Synchronize(doAllOver);
end;procedure TForm1.btnThreadStopClick(Sender: TObject);
begin
btnThreadStop.Enabled := False;
with TWaitThread.Create(True) do
begin
FreeOnTerminate := True;
OnAllOver := AllOver;
TA := FThreads;
Resume;
end;
end;procedure TForm1.AllOver(Sender: TObject);
begin
btnThreadStart.Enabled:= True;
end;procedure TForm1.btnThreadStartClick(Sender: TObject);
var
I: Integer;
begin
btnThreadStart.Enabled:= False;
SetLength(FThreads, 100);
for I := 0 to 99 do
begin
FThreads[I] := TTestThread.Create(True);
FThreads[I].FreeOnTerminate := True;
FThreads[I].Resume;
end;
btnThreadStop.Enabled := True;
end;
谢谢
虽然我没有测试。但我知道一定行
procedure TWaitThread.Execute;
begin
FreeOnTerminate := True; //我的作业线程里也加了这句,正常结束是会自自释放的吧
FOR I := 1 TO 88 DO
BEGIN
if Main_F.threadA[I] <> nil then
begin
Main_F.threadA[I].Terminate;
Main_F.threadA[I].WaitFor;
Main_F.FreeAndNil(threadA[I]); //这句要加吗 线程结束后,不是会自己释放吗?
end;
END;
end;
begin
FreeOnTerminate := True; //我的作业线程里也加了这句,正常结束是会自自释放的吧
FOR I := 1 TO 88 DO
BEGIN
//下面的部分你是要访问主线程中的数据(Main_F.threadA),
//你要保证你在这里操作这些数据的时候,主线程或者其他线程不会对Main_F.threadA进行些操作
if Main_F.threadA[I] <> nil then
begin
Main_F.threadA[I].Terminate; //结束,这没问题,记得在被结束的线程中要有对Terminated变量的判断
Main_F.threadA[I].WaitFor; //在这里等待其实不是一个好的方式,原因下面会说 //下面这句加上就会出错,因为你在线程中已经指定线程结束就释放自己
//Main_F.FreeAndNil(threadA[I]); //这句要加吗 线程结束后,不是会自己释放吗?
end;
END;
end;好了,说说你上面的过程,首先,在线程的释放过程中,就包含Terminate和WaitFor,因此,如果你采用这种方式来结束你的线程,那么,直接在循环中写
FOR I := 1 TO 88 DO
FreeAndNil(Main_F.threadA[I])
就可以,类的Free方法会主动判断被释放的类是否是nil,因此不用加入if Main_F.threadA[I] <> nil 的判断下面是线程类释放方法的一部分
destructor TThread.Destroy;
begin
if (FThreadID <> 0) and not FFinished then
begin
Terminate;
if FCreateSuspended then
Resume;
WaitFor;
end;
......
end;
从中可以看到,其释放方式还是很不错了,其中考虑到了如果线程挂起,就先回复他,呵呵,至少你和我写的代码中就没有考虑到好了,再说说为什么直接WaitFor不好。因此一旦waitFor,当前线程就会停下来,直到等待结束才继续,而采用Terminate的方式结束线程,是需要在线程函数中配合的,需要不时地检查 Terminated 变量,换句和说,Terminate的方式不时立刻就能把线程结束,他需要等到下一个对Terminated的判断才能退出线程函数,也就是说要消耗一些时间。所以,我在上面才先把线程句柄得到,然后集中调用所有线程的Terminate方法,这样,这些被停止的线程就能并行地去结束(至少在多核心的机器上是并行的),然后在后面采用等待函数去等待。而你写的函数,是线性地一个一个结束。差别就在这里。呵呵