新来的。对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;
这似乎适用于取消要求。我的理解是同步消息主线程并且它是执行包含DoStuff()的匿名过程的主线程,因此用户点击取消和有效权重之间应该没有竞争条件。(对吗?)
我坚持如何让称重线程只执行一次。我尝试过的各种解决方案导致了死锁(将Weigh.Free添加到DoStuff()......并没有花很长时间来弄清楚为什么这不起作用),单个执行但非自由线程(自我。在if块中的同步部分之后终止,或者其他各种废话。
那么,是否有可能让这个线程自由和/或自杀,同时仍允许通过用户输入的父线程杀死它,或者我是否需要一个完全不同的架构?
编辑以回应为什么循环:我只需要一个读数,但是直到我获得单个读数的时间在不同之间变化。天平可能需要几秒钟才能稳定,在此期间,每秒读取和显示不稳定的读数。仍然需要用户取消的能力,因为读数可能永远不会有效(超重)。
答案 0 :(得分:3)
如果我理解正确,您希望在完成调用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;
我不得不说这看起来更适合于计时器而不是线程。所有的工作都在主线程上完成,线程似乎只是定期检查一个标志。这听起来像个计时器。事实上,为什么连一个计时器?为什么不在设置标志为真时触发DoStuff
?