multithreading - Delphi - 在单次成功执行或用户取消后终止线程

标签 multithreading delphi delphi-xe3

这里是新的。对 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/

相关文章:

Delphi 多声道声卡 (ASIO)

delphi - TabSheet 可见的奇怪问题

java - 使用复选框在文本区域包装文本

java - 如何在 Java 中重用一个线程?

delphi - 需要一次将任何扩展名为XE5的一个字节的文件读入动态数组

delphi - 如何隐藏控制台窗口?

Delphi:如何将Click事件分配给对象的方法?

c++ - 锁定和操作需要很长时间

java - 可以单独访问的多个线程

windows - 动态与静态 DLL 链接不同