Fla*_*lyn 2 delphi multithreading terminate
我希望能够在点击按钮时终止一个线程,例如,如果用户需要,请将该过程停止一半.显然,你可以通过在线程中设置Terminated变量来实现这一点,这意味着你可以在退出之前执行某些代码而不是突然终止.
到目前为止的代码如下: -
单击启动线程
procedure TForm1.Panel29Click(Sender: TObject);
var
cmpfil : TThread;
begin
if (Edit3.Text <> '') AND (Edit4.Text <> '') then
begin
Form1.ProgressBar1.Min := 0;
Form1.Progressbar1.Max := 30000;
Form1.ProgressBar1.Position := 0;
cmpfiles := TCompareFilesThread.Create();
end;
end;
Run Code Online (Sandbox Code Playgroud)
创建线程
constructor TCompareFilesThread.Create;
begin
inherited Create(False);
end;
Run Code Online (Sandbox Code Playgroud)
实际线程
procedure TCompareFilesThread.Execute;
var
forg, fpat : file;
byteorg, bytepat : Array[0..1023] of byte;
i,z,o : integer;
fil1,fil2 : TFilename;
begin
//Form1.CompareFiles(FEdit3Text, FEdit4Text, FGrid, FOp, FProg);
begin
fil1 := Form1.Edit3.Text;
fil2 := Form1.Edit4.Text;
if Form1.CRCAdlerGenFile(fil1,1) <> Form1.CRCAdlerGenFile(fil2,1) then //Only Run if files arn't same
begin
op := 3;
synchronize(SetOP);
i := 0;
x := 1;
o := 0;
AssignFile(forg,fil1);
FileMode := fmOpenRead;
Reset(forg,1);
AssignFile(fpat,fil2);
FileMode := fmOpenRead;
Reset(fpat,1);
//Set Progress Bar
while NOT eof(forg) do
begin
while Terminated = False do
begin
BlockRead(forg,byteorg,1024);
BlockRead(fpat,bytepat,1024);
for z := 0 to 1023 do
begin
if byteorg[z] <> bytepat[z] then
begin
synchronize(sProgBarNext);
by := bytepat[z];
off := IntToStr(o);
synchronize(SyncGrid);
inc(x);
end;
inc(o);
end;
end;
end;
CloseFile(forg);
CloseFile(fpat);
end;
end;
Free;
end;
Run Code Online (Sandbox Code Playgroud)
我已经添加了While Terminated = False do一行,当更改时,该行将停止该过程.我似乎无法弄清楚如何改变它.我从未创造过那个变量; 它是内置的Delphi功能.我读过TMyThread.Terminate()但是我似乎无法确切地知道它的作用.它将Terminated设置为True还是只会杀死它所在的线程?
PS我还没有发布同步例程中的代码.一个打印到StringGrid,一个更新ProgressBar,第三个设置一个由StringGrid Sync例程使用的op变量,我没有看到这个代码与问题相关,但我可以发布请求.
是的,在您的线程对象上调用Terminate.它设置Terminated为true,就是这样 - 你的线程需要检查Terminated,就像你的代码一样(尽管有一个bug,见下文.)
更详细:您在此处创建线程对象:
cmpfiles := TCompareFilesThread.Create();
Run Code Online (Sandbox Code Playgroud)
让cmpfiles您的形式或其他类,而不是您的本地的成员变量Panel29Click的过程.nil在构造函数中初始化它.然后当您需要取消时,请致电:
if Assigned(cmpfiles) then begin
cmpfiles.Terminate;
end;
Run Code Online (Sandbox Code Playgroud)
如果线程存在,则设置Terminated标志.(编辑:感谢Rob,他建议避免使用FreeOnTerminate.我建议首先使用它是不好的建议.)你的线程还需要在完成时通知你的主线程,就在执行结束时,这样你就可以了可以释放它.一种方法是使用Synchronize通知主线程,然后在传递给Synchronize您的方法的主线程中释放线程对象.
FreeAndNil(cmpfiles);
Run Code Online (Sandbox Code Playgroud)
这样做在最后的Execute,因为线程对象将被删除-你不希望任何代码运行.
我发现的一个错误: 您的Execute代码具有以下两个while循环:
while NOT eof(forg) do
begin
while Terminated = False do
begin
...
end;
end;
Run Code Online (Sandbox Code Playgroud)
这实际上是在没有终止的情况下循环,它只会检查文件末尾Terminated是否设置为true.您可能希望循环同时检查两个条件,例如:
while (not eof(forg) and not Terminated) do
begin
...
end;
Run Code Online (Sandbox Code Playgroud)
哦,另一个错误,你的线程代码访问Form1的数据:
if Form1.CRCAdlerGenFile(fil1,1) <> Form1.CRCAdlerGenFile(fil2,1) then //Only Run if files arn't same
Run Code Online (Sandbox Code Playgroud)
这段代码是什么,在文件上运行CRC?如果CRCAdlerGenFile函数实际上没有触及Form1的任何部分,并且它只依赖于它的参数(并且它们是独立的),那么将它作为辅助函数在某处 - 它不必是类的一部分,你可以拥有独立功能.如果它依赖于Form1的部分,则不应该从您的线程代码中调用它.
| 归档时间: |
|
| 查看次数: |
544 次 |
| 最近记录: |