beginThread与CreateThread的区别解决思路
beginThread与CreateThread的区别
一个是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;
------解决方案--------------------
CreateThread是window提供的API函数
BeginThread是Delphi对CreateThread进一步的封装,内部实现时用到了CreateThread
function 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;
------解决方案--------------------
把MyThreadFunc作为BeginThread的参数有两个问题
1.P参数无效(MyThreadFunc会从栈顶获取,而实际上在EAX中传递过来)
2.函数无法正确返回(MyThreadFunc把栈顶的返回地址当成P参数了,而取了下一个不确定的元素作为返回地址)
所以在MyThreadFunc中加EndThread只是让线程在函数返回前结束执行,并不能解决第一个问题——而这可能会带来严重的错误,因为MyThreadFunc里P参数是一个指向代码段内存的地址(ThreadWrapper函数的执行体中某位置)。
另外看起来调用EndThread会造成BeginThread中分配的PThreadRec内存泄漏。
一个是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;
------解决方案--------------------
CreateThread是window提供的API函数
BeginThread是Delphi对CreateThread进一步的封装,内部实现时用到了CreateThread
function 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;
------解决方案--------------------
把MyThreadFunc作为BeginThread的参数有两个问题
1.P参数无效(MyThreadFunc会从栈顶获取,而实际上在EAX中传递过来)
2.函数无法正确返回(MyThreadFunc把栈顶的返回地址当成P参数了,而取了下一个不确定的元素作为返回地址)
所以在MyThreadFunc中加EndThread只是让线程在函数返回前结束执行,并不能解决第一个问题——而这可能会带来严重的错误,因为MyThreadFunc里P参数是一个指向代码段内存的地址(ThreadWrapper函数的执行体中某位置)。
另外看起来调用EndThread会造成BeginThread中分配的PThreadRec内存泄漏。