线程加上wairfor后使用出错?请高手指点! (50分)

  • 主题发起人 主题发起人 neom
  • 开始时间 开始时间
N

neom

Unregistered / Unconfirmed
GUEST, unregistred user!
简单的线程程序:
unit unitMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
procedure ThreadDone(sender: TObject);
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
uses unitThread;
{$R *.dfm}
var
ThreadRuning:integer;
MyThread1:TestThread;
MyThread2:TestThread;
procedure TForm1.Button1Click(Sender: TObject);
begin
ThreadRuning:=2;
MyThread1:=TestThread.Create(Edit1,10000);
MyThread1.OnTerminate:=ThreadDone;
MyThread2:=TestThread.Create(Edit2,10000);
MyThread2.OnTerminate:=ThreadDone;
Button1.enabled:=false;
end;

procedure TForm1.ThreadDone(Sender: TObject);
begin
dec(ThreadRuning);
if ThreadRuning=0 then
Button1.enabled:=true;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
if MyThread1<>nil then
try
MyThread1.Terminate;
MyThread1.WaitFor;
//MyTHread1.Free;
//MyThread1:=nil
except
showmessage('freed');
end;
end;

end.

unit unitThread;
interface
uses
Classes, StdCtrls, SysUtils {$IFDEF MSWINDOWS} , Windows {$ENDIF};
type
TestThread = class(TThread)
private
AEdit:TEdit;
MaxLoop:integer;
CurrentLoop:integer;
procedure SetName;
protected
procedure Execute;
override;
procedure DisLoop;
public
constructor Create(Edit:TEdit;Max:integer);
end;

implementation
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TestThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end;
}
{$IFDEF MSWINDOWS}
type
TThreadNameInfo = record
FType: LongWord;
// must be 0x1000
FName: PChar;
// pointer to name (in user address space)
FThreadID: LongWord;
// thread ID (-1 indicates caller thread)
FFlags: LongWord;
// reserved for future use, must be zero
end;
{$ENDIF}
{ TestThread }
constructor TestThread.Create(Edit:TEdit;Max:integer);
begin
inherited Create(false);
AEdit:=Edit;
MaxLoop:=Max;
FreeOnTerminate:=true;
end;

procedure TestThread.SetName;
{$IFDEF MSWINDOWS}
var
ThreadNameInfo: TThreadNameInfo;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
ThreadNameInfo.FType := $1000;
ThreadNameInfo.FName := 'tmpThread';
ThreadNameInfo.FThreadID := $FFFFFFFF;
ThreadNameInfo.FFlags := 0;
try
RaiseException( $406D1388, 0, sizeof(ThreadNameInfo) div sizeof(LongWord), @ThreadNameInfo );
except
end;
{$ENDIF}
end;

procedure TestThread.Execute;
var
i:integer;
begin
SetName;
{ Place thread code here }
for i:=0 to MaxLoopdo
begin
CurrentLoop:=i;
Synchronize(DisLoop);
if terminated then
exit;
end;
end;

procedure TestThread.DisLoop;
begin
AEdit.Text:=IntToStr(CurrentLoop);
end;

end.

F9运行时点start 然后点terminate
出现如下错误:
raise exception error with message 'Thread error 句柄无效。(6)'
 
-->FreeOnTerminate:=true;
so:
MyThread1.Terminate;
后MyThread1不一定还存在,如果线程执行够快则资源已经释放调了,此时调MyThread1.WaitFor当然会报错,因为1.MyTheard1中关于线程部分的资源已经可能释放调了,2.MyThread1本身可能也已经释放调了。
你可以理解为:
MyThread1.WaitFor与MyThread1.Free在同时执行, hehe,后果我就不说了。
 
接受答案了.
 
后退
顶部