function ThreadPro(lparam: Pointer): DWORD; stdcall; begin Result := 0; end;procedure TForm1.Button1Click(Sender: TObject); var ThreadHandle: THandle; ThreadId, EixtCode: DWORD; IsExist: Boolean; begin ThreadHandle := CreateThread(nil, 0, @ThreadPro, nil, 0, ThreadId); try IsExist := GetExitCodeThread(ThreadHandle, EixtCode); if IsExist then begin if ExitCode = STILL_ACTIVE then ShowMessage('Thread Active') else ShowMessage('Thread Function Exit'); end else ShowMessage('Thread Exit'); finally CloseHandle(ThreadHandle); end
function ThreadPro(lparam: Pointer): DWORD; stdcall; begin Result := 0; end;procedure TForm1.Button1Click(Sender: TObject); var ThreadHandle: THandle; ThreadId, EixtCode: DWORD; IsExist: Boolean; begin ThreadHandle := CreateThread(nil, 0, @ThreadPro, nil, 0, ThreadId); try IsExist := GetExitCodeThread(ThreadHandle, EixtCode); if IsExist then begin if ExitCode = STILL_ACTIVE then ShowMessage('Thread Active') else ShowMessage('Thread Function Exit'); end else ShowMessage('Thread Exit'); finally CloseHandle(ThreadHandle); end
完善下,应该符合楼主的想法function ThreadPro(lparam: Pointer): DWORD; stdcall; begin Result := DWORD(TStringList.Create); with TStringList(Result) do begin Add('1'); Add('2'); Add('3'); Add('4'); end; end;procedure TForm1.BitBtn1Click(Sender: TObject); var ThreadHandle: THandle; ThreadId, EixtCode: DWORD; begin ThreadHandle := CreateThread(nil, 0, @ThreadPro, nil, 0, ThreadId); if ThreadHandle > 0 then begin WaitForSingleObject(ThreadHandle,INFINITE); if GetExitCodeThread(ThreadHandle, EixtCode) then begin if (EixtCode > 10) then begin with TStringList(EixtCode) do Caption := Format('Count:%d; CommandText:%s', [Count, CommaText]); TStringList(EixtCode).Free; end; end; CloseHandle(ThreadHandle); end; end;
针对8楼的观点,我将上面的代码改动了下,经过测试,Caption中显示的释放计数是0 ShowMessage显示出来的释放计数是1,而且,线程中创建的列表,在线程结束后,其内容依然可以被访问,所以,其占用的内存依然存在。 所以,8楼说的是不正确的。 在线程中创建的TStringList,在线程结束时,如果没有显示地释放,那么这个类是不会随着线程的结束而被释放。验证代码如下: type TMyList = class(TStringList) public destructor Destroy; override; end;var FreeCount: Integer = 0;
{ TMyList }destructor TMyList.Destroy; begin Inc(FreeCount); inherited; end;
function ThreadPro(lparam: Pointer): DWORD; stdcall; begin Result := DWORD(TMyList.Create); with TStringList(Result) do begin Add('1'); Add('2'); Add('3'); Add('4'); end; end;procedure TForm1.BitBtn1Click(Sender: TObject); var ThreadHandle: THandle; ThreadId, EixtCode: DWORD; begin ThreadHandle := CreateThread(nil, 0, @ThreadPro, nil, 0, ThreadId); if ThreadHandle > 0 then begin WaitForSingleObject(ThreadHandle,INFINITE); if GetExitCodeThread(ThreadHandle, EixtCode) then begin if (EixtCode > 10) then begin with TStringList(EixtCode) do Caption := Format('FreeCount:%d; Count:%d; CommandText:%s', [FreeCount, Count, CommaText]); TStringList(EixtCode).Free; ShowMessage(IntToStr(FreeCount)); end; end; CloseHandle(ThreadHandle); end; end;
ExitCode: Integer;
begin
GetExitCodeThread(ThreadHandle, ExitCode);
ShowMessage('The exit code is ' + IntToStr(ExitCode));
end;
ExitCode=cardinal
糟糕行为是,当线程还在进行,尚未有所谓的结束代码时,它会传回TRUE表示成功,如果
这样, lpExitCode 指向的内存区域中应该放的时STILL_ACTIVE,你必须小心这种行为
,也就是说你不可能从其返回值中知道"到底是线程还在运行呢,还是它已经结束,但返回
值为 STILL_ACTIVE"GetExitCodeThread() 的返回值应该是 TRUE 或者 FALSE, 尽管 BOOL 实际上是 typedef int BOOL, 即 GetExitCodeThread() 的返回值只表示该函数本身执行是否成功并不是说对应线程如果结束了GetExitCodeThread() 函数就必须返回其结束代码,线程是否结束与该函数的返回值根本就是两码事,GetExitCodeThread() 函数返回 FALSE 的唯一情况应该是它无法确定其检测线程的状态.而这里却以其返回值来判断被检测线程是否结束,并说GetExitCodeThread() 的返回值是一种" 糟糕的行为" ,这很没道理,该函数设计的目的就是获取一个线程结束时的返回值,本来就不是用来检测一个线程是否结束,当然如果能够保证线程不将 STILL_ACTIVE 作为错误码返回也可以用来检测线程是否结束.
function ThreadPro(lparam: Pointer): DWORD; stdcall;
begin
Result := 0;
end;procedure TForm1.Button1Click(Sender: TObject);
var
ThreadHandle: THandle;
ThreadId, EixtCode: DWORD;
IsExist: Boolean;
begin
ThreadHandle := CreateThread(nil, 0, @ThreadPro, nil, 0, ThreadId); try
IsExist := GetExitCodeThread(ThreadHandle, EixtCode);
if IsExist then
begin
if ExitCode = STILL_ACTIVE then
ShowMessage('Thread Active')
else
ShowMessage('Thread Function Exit');
end
else
ShowMessage('Thread Exit'); finally
CloseHandle(ThreadHandle);
end
function ThreadPro(lparam: Pointer): DWORD; stdcall;
begin
Result := 0;
end;procedure TForm1.Button1Click(Sender: TObject);
var
ThreadHandle: THandle;
ThreadId, EixtCode: DWORD;
IsExist: Boolean;
begin
ThreadHandle := CreateThread(nil, 0, @ThreadPro, nil, 0, ThreadId); try
IsExist := GetExitCodeThread(ThreadHandle, EixtCode);
if IsExist then
begin
if ExitCode = STILL_ACTIVE then
ShowMessage('Thread Active')
else
ShowMessage('Thread Function Exit');
end
else
ShowMessage('Thread Exit'); finally
CloseHandle(ThreadHandle);
end
begin
Result := DWORD(TStringList.Create);
with TStringList(Result) do
begin
Add('1');
Add('2');
Add('3');
Add('4');
end;
end;procedure TForm1.BitBtn1Click(Sender: TObject);
var
ThreadHandle: THandle;
ThreadId, EixtCode: DWORD;
begin
ThreadHandle := CreateThread(nil, 0, @ThreadPro, nil, 0, ThreadId);
if ThreadHandle > 0 then
begin
WaitForSingleObject(ThreadHandle,INFINITE);
if GetExitCodeThread(ThreadHandle, EixtCode) then
begin
if (EixtCode > 10) then
begin
with TStringList(EixtCode) do
Caption := Format('Count:%d; CommandText:%s',
[Count, CommaText]); TStringList(EixtCode).Free;
end;
end;
CloseHandle(ThreadHandle);
end;
end;
针对8楼的观点,我将上面的代码改动了下,经过测试,Caption中显示的释放计数是0
ShowMessage显示出来的释放计数是1,而且,线程中创建的列表,在线程结束后,其内容依然可以被访问,所以,其占用的内存依然存在。
所以,8楼说的是不正确的。
在线程中创建的TStringList,在线程结束时,如果没有显示地释放,那么这个类是不会随着线程的结束而被释放。验证代码如下:
type
TMyList = class(TStringList)
public
destructor Destroy; override;
end;var
FreeCount: Integer = 0;
{ TMyList }destructor TMyList.Destroy;
begin
Inc(FreeCount);
inherited;
end;
function ThreadPro(lparam: Pointer): DWORD; stdcall;
begin
Result := DWORD(TMyList.Create);
with TStringList(Result) do
begin
Add('1');
Add('2');
Add('3');
Add('4');
end;
end;procedure TForm1.BitBtn1Click(Sender: TObject);
var
ThreadHandle: THandle;
ThreadId, EixtCode: DWORD;
begin
ThreadHandle := CreateThread(nil, 0, @ThreadPro, nil, 0, ThreadId);
if ThreadHandle > 0 then
begin
WaitForSingleObject(ThreadHandle,INFINITE);
if GetExitCodeThread(ThreadHandle, EixtCode) then
begin
if (EixtCode > 10) then
begin
with TStringList(EixtCode) do
Caption := Format('FreeCount:%d; Count:%d; CommandText:%s',
[FreeCount, Count, CommaText]); TStringList(EixtCode).Free;
ShowMessage(IntToStr(FreeCount));
end;
end;
CloseHandle(ThreadHandle);
end;
end;