500分求解: 如何立即杀死正在运行的线程?(300分)

  • 主题发起人 主题发起人 luckystart
  • 开始时间 开始时间
L

luckystart

Unregistered / Unconfirmed
GUEST, unregistred user!
以前问过,但是一直没有好的解决方法。
现在向各位DFW高分征解。
要求:
1、可以立即杀死正在运行的线程;
2、不会造成内存泄漏;
3、易用。
(不要告诉我直接关闭程序。)
比如有个线程的execute为:
procedure mythread.execute;
begin
while truedo
begin
application.processmessages;
end;
end;
要求点击主程序上的按钮,可以马上杀死该线程,
且没有内存泄漏。
提供源码,验证通过后,马上给分。
剩下的200分我会另外给。
 
把所有的线程都加上:
yourthread.Terminate;
youthread.waitfor;
yourthread.free;
....free;//其他自己定义的资源释放。
不要只用terminate,因为这样只是把线程的onterminatefree标志为true。
 
TerminateThread(Handle,ExitCode)
 
源码有的,你装个BCB,它就自带有一个这样的示例程序,你一看就明白了.
 
请提供验证有效的源码。
 
以前的贴子http://www.delphibbs.com/delphibbs/dispq.asp?LID=915786,以知道能
否解决你产问题
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
ListBox1: TListBox;
Label1: TLabel;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
Wnd: HWND;
implementation
{$R *.DFM}
Function EnumWindowsProc (Wnd: HWND;
lb: TListbox): BOOL;
stdcall;
var
caption: Array [0..128] of Char;
begin
Result := True;
if { skip invisible windows }
IsWindowVisible(Wnd) and
{ only process truly top-level windows. GetWindowLong must be used,
not
GetParent }
((GetWindowLong(Wnd, GWL_HWNDPARENT) = 0) or
(HWND(GetWindowLong(Wnd, GWL_HWNDPARENT)) = GetDesktopWindow)) and
{ skip WS_EX_TOOLWINDOW windows }
((GetWindowLong(Wnd, GWL_EXSTYLE) and WS_EX_TOOLWINDOW) = 0)
then
begin
SendMessage( Wnd, WM_GETTEXT, Sizeof( caption ), integer(@caption));
lb.Items.AddObject( caption, TObject( Wnd ));
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
listbox1.clear;
EnumWindows( @EnumWindowsProc, integer( listbox1 ));
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var
theClassname: Array [0..128] of Char;
tid, pid: DWORD;
intExitCode:DWORD;
begin
With Sender As TListboxdo
begin
If ItemIndex >= 0 then
begin
Wnd:= HWND(Items.Objects[ itemindex ]);
If Wnd <> 0 then
begin
Windows.GetClassname( Wnd, theClassname, Sizeof( classname ));
tid := GetWindowThreadProcessID( Wnd, @pid );
label1.caption :=
Format(
'HWND: %8.8x'#13#10+
'Class: %s'#13#10+
'Process ID: %8.8x'#13#10+
'Thread ID: %8.8x',
[Wnd, theClassname, pid, tid] );
end;
end;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
PostMessage(Wnd, WM_CLOSE, 0, 0);
end;

end.
 
要一点内存泄漏都没有,只能用一个标志让线程自己退出
(比如thread.Terminate就是设置thread.Terminated属性,线程自己检测到以后自己退出)
但是如果要无条件立即杀死线程,而且本进程不退出,那么线程的一些资源是不会立即释放的
只有等到整个进程退出为止
如果要做到本进程不退出、线程立即杀死、线程申请的资源立即释放,那么你是否可以用子进程
来代替线程呢,杀死子进程就释放了子进程的资源
 
pipi能不能详细点?
 
〉〉1、可以立即杀死正在运行的线程;
〉〉2、不会造成内存泄漏;
1,2两条是矛盾的,我觉得不可能做到。
 
建議你是還在將該線程的execute的迴圈加上結速時的判斷, 讓線程自動退出, 否則因
在Delphi的機制中, 如果直接以API 殺死線程, Delphi本身保留的線程類(TThread)實例
並無法釋放, 還是會導致應用程序在結束時, 發生內存存取錯誤!
可以將Execute改為如下
procedure mythread.execute;
begin
while not Terminateddo
begin
application.processmessages;
end;
end;
要釋放該線程時, 可以在button中加入
FreeAndNil(FMyThread) 或 FMyThread.Free或 FMyThread.Terminate;都可以;
注意, 如果Thread的FreeOnTerminate不為True, 在調用Terminate時, 線程是結束了,
但線程實例(TThread實例)並不會被釋放
 
FreeOnTerminate:true;
yourThread.suspend;
yourthread.free;
 
来自:savenight, 时间:2002-4-18 19:27:00, ID:1052643
〉〉1、可以立即杀死正在运行的线程;
〉〉2、不会造成内存泄漏;
1,2两条是矛盾的,我觉得不可能做到。
同意pipi你把线程换成子进程!
 
简单的terminate肯定是不行的。因为有些网络操作会失去响应。
Free destroy我都试过,都不能释放内存。
关于进程我不太了解。哪些老兄帮忙给个简单一点的例子看看?
 
the way i did is adding more Thread.Teminated check into the code,
and write a garbage cleaner thread that can check and free all the resource of
terminaated thread in interval.
 
同意lorderic
如果循环体很大的话你还可以在循环体内加
if Terminated then
exit
 
多人接受答案了。
 
后退
顶部