我有一个button1
和一个label1
。button1
单击 时,label1
开始在其自己的线程上进行计数。
问题是,当我单击时,我无法停止该线程button2
。
这是我正在使用的代码:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls, System.SyncObjs;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
public
end;
{ TMyThread is the class that will handle background work for Label1 }
MyThread1 = class(TThread)
private
count: Integer;
msg: string;
stopThread:boolean;
protected
procedure Execute; override;
procedure UpdateUI;
public
constructor Create;
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
{ MyThread Constructor }
constructor MyThread1.Create;
begin
inherited Create(False); // False means it will start right away
FreeOnTerminate := True; // Free memory when finished
end;
{ Worker Thread for Label1 }
procedure MyThread1.Execute;
var
i: Integer;
begin
for i := 1 to 1000 do
begin
//Check to see if the was terminated. If so, then exit the for loop.
if Terminated then
Exit;
Sleep(10); // Simulate work (1 second per iteration)
msg := '# ' + IntToStr(i);
Synchronize(UpdateUI); // Update UI safely from the main thread
end;
Synchronize(UpdateUI);
end;
{ Update the UI for Label1 }
procedure MyThread1.UpdateUI;
begin
Inc(count);
Form1.Label1.Text := msg;
//WHen finished:
if (count = 1000) then
begin
ShowMessage('Thread 1 Finished!');
end;
end;
{Start the thread when button1 is clicked}
procedure TForm1.Button1Click(Sender: TObject);
begin
MyThread1.Create; // Create and start the first thread for Label1
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
//Procedure to stop the MyThread1 thread goes here.
end;
end.
我试图停止该线程,但它没有停止。
我无法终止该线程到底是什么问题?
最佳答案
1
您没有使用该stopThread
成员,因此请将其删除。您的线程Execute()
代码正在查看线程的Terminated
属性,因此请调用线程的Terminate()
方法。
但是,您button1
没有保存它创建的线程对象,因此button2
无法访问它。
尝试一些更像这样的事情:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.Controls.Presentation, FMX.StdCtrls, System.SyncObjs;
type
MyThread1 = class;
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
FMyThread: MyThread1:
procedure ThreadTerminated(Sender: TObject);
public
end;
{ TMyThread is the class that will handle background work for Label1 }
MyThread1 = class(TThread)
private
count: Integer;
msg: string;
protected
procedure Execute; override;
procedure UpdateUI;
public
constructor Create;
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
{ MyThread Constructor }
constructor MyThread1.Create;
begin
inherited Create(True); // True means it will not start right away
FreeOnTerminate := True; // Free memory when finished
end;
{ Worker Thread for Label1 }
procedure MyThread1.Execute;
var
i: Integer;
begin
for i := 1 to 1000 do
begin
//Check to see if the thread was terminated. If so, then exit the for loop.
if Terminated then
Break;
Sleep(10); // Simulate work (1 second per iteration)
msg := '# ' + IntToStr(i);
Synchronize(UpdateUI); // Update UI safely from the main thread
end;
Synchronize(UpdateUI);
end;
{ Update the UI for Label1 }
procedure MyThread1.UpdateUI;
begin
Inc(count);
Form1.Label1.Text := msg;
end;
{Start the thread when button1 is clicked}
procedure TForm1.Button1Click(Sender: TObject);
begin
if FMyThread <> nil then Exit;
FMyThread := MyThread1.Create; // Create and start the first thread for Label1
FMyThread.OnTerminate := ThreadTerminated;
FMyThread.Start;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
//Procedure to stop the MyThread1 thread goes here.
if FMyThread <> nil then
FMyThread.Terminate;
end;
procedure TForm1.ThreadTerminated(Sender: TObject);
begin
//WHen finished:
FMyThread := nil;
ShowMessage('Thread 1 Finished!');
end;
end.
3
-
1) FMyThread<>nil 的测试、2) FMyThread:=nil 和 3) FMyThread.Terminate 之间是否存在竞争条件?
– -
2@AndersMelander 不,因为所有这三个操作都是在主线程中完成的。
TThread.OnTerminate
默认情况下,事件是同步的(您可以覆盖TThread.DoTerminate()
以更改这一点)
–
-
是的你是对的。
–
|
|