以下程序运行时出错,出错描述如下:
主窗口有两个按钮,一个按钮创建线程,一个按钮调用Terminate使线程中止,调用后有个while语句判断主局变量是否为True,如果不是True,一直循环,当中止线程时,会出现进入progressAddOne函数,不会出来(可以从日志中显示出来),程序就一直在while中循环,也就是flag := True;这条语句没有执行到.
以下为主窗口
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, Unit2;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
testtheardtmp: testtheard;
flag: Boolean;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
testtheardtmp := testtheard.create;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
testtheardtmp.Terminate;
while not flag do
sleep(10);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
flag := False;
end;
end.//以下为线程单元
unit Unit2;
interface
uses
Classes, Sysutils, FileCtrl, windows, progressfrm, extctrls, Controls;
type
testtheard = class(TThread)
private
ffrmprogress: Tfrmprogress;
{ Private declarations }
protected
//进度条初始化
procedure progressIni;
//进度条加一
procedure progressAddOne;
procedure freeform;
procedure Execute; override;
public
constructor Create;
end;
implementation
uses
Unit1;
{ testtheard }
constructor testtheard.Create;
begin
ffrmprogress := Tfrmprogress.Create(nil);
ffrmprogress.show;
flag := False;
FreeOnTerminate := False;
inherited Create(False);
end;
procedure testtheard.Execute;
begin
Synchronize(progressIni);
while not Terminated do
begin
sleep(10);
WriteLog('thread.txt', '进入<progressAddOne>'); //写日志
Synchronize(progressAddOne);
WriteLog('thread.txt', '出来<progressAddOne>'); //写日志
end;
WriteLog('thread.txt', '进入<freeform>'); //写日志
freeform;
WriteLog('thread.txt', '出来<freeform>'); //写日志
flag := True;
end;
procedure testtheard.freeform;
begin
ffrmprogress.free;
end;
procedure testtheard.progressAddOne;
begin
ffrmprogress.ProgressBar1.Position := ffrmprogress.ProgressBar1.Position + 1;
end;
procedure testtheard.progressIni;
begin
ffrmprogress.ProgressBar1.Max := 10000;
ffrmprogress.ProgressBar1.Position := 0;
end;
end.//以下为进度条窗口
unit progressfrm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Gauges, StdCtrls, ExtCtrls, ComCtrls;
type
Tfrmprogress = class(TForm)
Panel1: TPanel;
ProgressBar1: TProgressBar;
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.DFM}
end.
主窗口有两个按钮,一个按钮创建线程,一个按钮调用Terminate使线程中止,调用后有个while语句判断主局变量是否为True,如果不是True,一直循环,当中止线程时,会出现进入progressAddOne函数,不会出来(可以从日志中显示出来),程序就一直在while中循环,也就是flag := True;这条语句没有执行到.
以下为主窗口
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, Unit2;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
testtheardtmp: testtheard;
flag: Boolean;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
testtheardtmp := testtheard.create;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
testtheardtmp.Terminate;
while not flag do
sleep(10);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
flag := False;
end;
end.//以下为线程单元
unit Unit2;
interface
uses
Classes, Sysutils, FileCtrl, windows, progressfrm, extctrls, Controls;
type
testtheard = class(TThread)
private
ffrmprogress: Tfrmprogress;
{ Private declarations }
protected
//进度条初始化
procedure progressIni;
//进度条加一
procedure progressAddOne;
procedure freeform;
procedure Execute; override;
public
constructor Create;
end;
implementation
uses
Unit1;
{ testtheard }
constructor testtheard.Create;
begin
ffrmprogress := Tfrmprogress.Create(nil);
ffrmprogress.show;
flag := False;
FreeOnTerminate := False;
inherited Create(False);
end;
procedure testtheard.Execute;
begin
Synchronize(progressIni);
while not Terminated do
begin
sleep(10);
WriteLog('thread.txt', '进入<progressAddOne>'); //写日志
Synchronize(progressAddOne);
WriteLog('thread.txt', '出来<progressAddOne>'); //写日志
end;
WriteLog('thread.txt', '进入<freeform>'); //写日志
freeform;
WriteLog('thread.txt', '出来<freeform>'); //写日志
flag := True;
end;
procedure testtheard.freeform;
begin
ffrmprogress.free;
end;
procedure testtheard.progressAddOne;
begin
ffrmprogress.ProgressBar1.Position := ffrmprogress.ProgressBar1.Position + 1;
end;
procedure testtheard.progressIni;
begin
ffrmprogress.ProgressBar1.Max := 10000;
ffrmprogress.ProgressBar1.Position := 0;
end;
end.//以下为进度条窗口
unit progressfrm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Gauges, StdCtrls, ExtCtrls, ComCtrls;
type
Tfrmprogress = class(TForm)
Panel1: TPanel;
ProgressBar1: TProgressBar;
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.DFM}
end.
可以用API函数TERMINATETHREAD()强行中止线程,但这样线程所占用的资源不会得到释放,也不会关闭已经打开的文件.
首先你释放窗体应该在线程Destroy 的时候释放
destructor Destroy; override;
destructor testtheard.Destroy;
begin
freeform; WriteLog('thread.txt', '进入<freeform>'); //写日志
WriteLog('thread.txt', '出来<freeform>'); //写日志
flag := True;
inherited;
end;
其次
procedure TForm1.Button2Click(Sender: TObject);
begin
testtheardtmp.Terminate;
//当你执行Terminate 的时候只是发送了一个命令, 线程有可以还在执行但还没有完成, 所以你下面可能会进行死循环
while not flag do
sleep(10);
end;, 正确的写法应该是在Destroy的时个设置Flag destructor testtheard.Destroy;
begin
freeform;
inherited;
end;