一个是delphi的一个是api,我看书没看出他们的区别,但是以下的程序换成beginThread则会有问题。
type
TForm1 = class(TForm)
Button2: TButton;
Button3: TButton;
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}
function MyThreadFunc(P:pointer):Longint;stdcall;
var
i:integer;
DC:HDC;
S:string;
begin
Result := 0;
DC:=GetDC(Form1.Handle);
for i:=0 to 100000 do
begin
S:=Inttostr(i);
Textout(DC,10,10,Pchar(S),length(S));
end;
ReleaseDC(Form1.Handle,DC);
end;procedure TForm1.Button2Click(Sender: TObject);
var
hThread:Thandle;//定义一个句柄
ThreadID:DWord;
begin
//创建线程,同时线程函数被调用 hthread:=CreateThread(nil,0,@MyThreadfunc, nil, 0,ThreadID);
//hthread:=BeginThread(nil,0,@MyThreadfunc, nil, 0,ThreadID);
if hThread=0 then
begin
messagebox(Handle,'Didn’t Create a Thread',nil,MB_OK);
end;
end;procedure TForm1.Button3Click(Sender: TObject);
begin
MyThreadfunc(nil);
end;
type
TForm1 = class(TForm)
Button2: TButton;
Button3: TButton;
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}
function MyThreadFunc(P:pointer):Longint;stdcall;
var
i:integer;
DC:HDC;
S:string;
begin
Result := 0;
DC:=GetDC(Form1.Handle);
for i:=0 to 100000 do
begin
S:=Inttostr(i);
Textout(DC,10,10,Pchar(S),length(S));
end;
ReleaseDC(Form1.Handle,DC);
end;procedure TForm1.Button2Click(Sender: TObject);
var
hThread:Thandle;//定义一个句柄
ThreadID:DWord;
begin
//创建线程,同时线程函数被调用 hthread:=CreateThread(nil,0,@MyThreadfunc, nil, 0,ThreadID);
//hthread:=BeginThread(nil,0,@MyThreadfunc, nil, 0,ThreadID);
if hThread=0 then
begin
messagebox(Handle,'Didn’t Create a Thread',nil,MB_OK);
end;
end;procedure TForm1.Button3Click(Sender: TObject);
begin
MyThreadfunc(nil);
end;
BeginThread是Delphi对CreateThread进一步的封装,内部实现时用到了CreateThreadfunction BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
var ThreadId: LongWord): Integer;
var
P: PThreadRec;
begin
New(P);
P.Func := ThreadFunc;
P.Parameter := Parameter;
IsMultiThread := TRUE;
Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
CreationFlags, ThreadID);
end;
一件是设置了IsMultiThread := TRUE;
这个全局变量在很多地方要用到,比如分配内存、COM应用时
另一件是在ThreadWrapper里加入了异常保护你的那段代码出错,是因为没有调用EndThreadfunction MyThreadFunc(P:pointer):Longint;stdcall;
var
i:integer;
DC:HDC;
S:string;
begin
Result := 0;
DC:=GetDC(Form1.Handle);
for i:=0 to 100000 do
begin
S:=Inttostr(i);
Textout(DC,10,10,Pchar(S),length(S));
end;
ReleaseDC(Form1.Handle,DC);
EndThread(0);
end;procedure TForm1.Button1Click(Sender: TObject);
var
hThread:Thandle;//定义一个句柄
ThreadID:DWord;
begin
//创建线程,同时线程函数被调用 hthread:=BeginThread(nil,0,@MyThreadfunc, nil,0,ThreadID);
if hThread=0 then
begin
messagebox(Handle,'Didn’t Create a Thread',nil,MB_OK);
end;
end;
public
procedure DoAnyThing;
end; TChildBase=class
public
procedure DoAnyThing;
end; TParent=class(TParentBase)
private
FChild : TChildBase;
end; TChild=class(TChildBase)
private
FParent : TParentBase;
end;
procedure DoAnyThing;
end; IChild=Interface
procedure DoAnyThing;
end; TParent=class(TObject,IParent)
private
FChild : IChild;
end; TChild=class(TObject,IChild)
private
FParent : IParent;
end;
1.P参数无效(MyThreadFunc会从栈顶获取,而实际上在EAX中传递过来)
2.函数无法正确返回(MyThreadFunc把栈顶的返回地址当成P参数了,而取了下一个不确定的元素作为返回地址)
所以在MyThreadFunc中加EndThread只是让线程在函数返回前结束执行,并不能解决第一个问题——而这可能会带来严重的错误,因为MyThreadFunc里P参数是一个指向代码段内存的地址(ThreadWrapper函数的执行体中某位置)。
另外看起来调用EndThread会造成BeginThread中分配的PThreadRec内存泄漏。