这里是新的。对 Delphi 来说也相对较新,所以请友善......
我的实际(域)问题:小型 VCL 应用程序通过串行方式与两个实验室天平进行通信,以连续 1 秒的间隔输出天平重量读数,所述重量显示在两个标签的标题中。当用户单击“称重”按钮时,我需要等待有效的重量(稳定、在范围内等)并记录一次所述重量,或者允许用户取消称重。
我的问题已实现。当用户单击称重按钮时,使用 S.MAHDI/David Heffernan 的 TEvent 模板创建单独的线程,如 this post 所示。 .
TWeigh = class(TThread)
private
FTerminateEvent: TEvent;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create(ACreateSuspended: Boolean);
destructor Destroy; override;
end;
constructor TWeigh.Create(ACreateSuspended: Boolean);
begin
FTerminateEvent := TEvent.Create(nil, True, False, '');
inherited;
end;
destructor TWeigh.Destroy;
begin
inherited;
FTerminateEvent.Free;
end;
procedure TWeigh.TerminatedSet;
begin
FTerminateEvent.SetEvent;
Beep;
end;
procedure TWeigh.Execute();
begin
while (not Terminated) do begin
if (validweight) then begin
Synchronize(procedure begin
DoStuff();
end);
end;
FTerminateEvent.WaitFor(100);
end;
end;
我的表单按钮单击事件如下所示:
{ Weigh is global implementation var of class TWeigh }
procedure TForm1.btnWeighClick(Sender: TObject);
var
B : TButton;
begin
B := Sender as TButton;
if (B.Caption = 'Weigh') then Weigh := TWeigh.Create(False);
if (B.Caption = 'Cancel') then Weigh.Free;
B.Caption := Trim(Copy('CancelWeigh ',AnsiPos(B.Caption,'Weigh Cancel'),6));
end;
这似乎可以很好地满足取消要求。据我了解,Synchronize 向主线程发送消息,并且它是执行包含 DoStuff() 的匿名过程的主线程,因此用户单击取消和传入有效权重之间不应该存在竞争条件。(对吗?)
我陷入了如何让称重线程只执行一次的困境。我尝试过的各种解决方案都导致了死锁(将 Weigh.Free 添加到 DoStuff()...没花很长时间就弄清楚为什么这不起作用)、单次执行但非释放线程(self.在 if block 内的同步部分之后终止),或各种其他废话。
那么,是否有可能让这个线程自由和/或杀死自己,同时仍然允许父线程通过用户输入杀死它,或者我是否需要一个完全不同的架构?
编辑以回应循环的原因:我只需要一次读数,但获得该读数的时间在立即和从不之间变化。天平可能需要几秒钟才能稳定,在此期间每秒都会读取并显示不稳定的读数。仍然需要用户取消的能力,因为读数可能永远无效(重量不足)。
最佳答案
如果我理解正确的话,您希望在调用完 DoStuff
后退出线程。可以这样做:
procedure TWeigh.Execute();
begin
while (not Terminated) do begin
if (validweight) then begin
Synchronize(procedure begin
DoStuff();
end);
exit;
end;
FTerminateEvent.WaitFor(100);
end;
end;
我不得不说,这看起来比线程更适合计时器。所有工作都是在主线程上完成的,并且该线程似乎只是定期检查标志。这听起来像一个计时器。事实上,为什么还要一个计时器呢?当您将标志设置为 true 时,为什么不触发 DoStuff
?
关于multithreading - Delphi - 在单次成功执行或用户取消后终止线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22569623/