【问题标题】:Why timer (system.windows.forms.timer) won't start?为什么计时器(system.windows.forms.timer)不会启动?
【发布时间】:2012-11-09 16:37:27
【问题描述】:

在用户定义的类中,我有一个计时器,当我Timer.Enabled.时它不会启动

用户定义的类:

  TSerialIndicator = public class
  private
    method TxTimerEvent(Sender:System.Object; e:System.EventArgs);
  public    
    Txlight:Label;
    Txtimer:System.Windows.Forms.Timer;
    constructor(mform:Form);
    method Transmit;
    method Receive;
  end;

这里是构造函数:

constructor TSerialIndicator(mform:Form);
begin
    TxLight := new Label;

    TxLight.AutoSize := false;

    TxLight.BorderStyle := BorderStyle.FixedSingle;

    TxLight.Location := new point(52,163);

    TxLight.Width := 20;
    TxLight.Height := 20;

    mform.Controls.Add(TxLight);

    TxTimer := new System.Windows.Forms.Timer;
    TxTimer.Interval:=1;

    TxTimer.Enabled:=false;
    TxTimer.Tick += new System.EventHandler(@TxTimerEvent);

    TxLight.BackColor := Color.Black;
end;

这是定义的传输方法:

method TSerialIndicator.Transmit;
begin
  TxLight.BackColor := Color.Red;

  if TxTimer.Enabled = false then
     TxTimer.Enabled:=true;
end;

这里是定义的 TxTimerEvent:

method TSerialIndicator.TxTimerEvent(Sender:System.Object; e:System.EventArgs);
begin
    TxLight.BackColor := Color.Black;
    TxTimer.Enabled:=false;
end;

以下是它的创建和使用方式:

Slight := new TSerialIndicator(self);
Slight.Transmit;

当我从程序的其他部分调用 Transmit 时,它会做它的事情,但 TxTimerEvent 永远不会触发。我什至尝试过启动/停止它的方法。它仍然没有执行它的 Tick 事件。但是,我确实注意到,当我在构造函数中启用计时器时,它确实会触发 TxTimerEvent ONCE。

我做错了什么?

提前致谢,

【问题讨论】:

  • 这看起来不像 C#...
  • @akatakritos,我最初有 50 个,但它仍然没有被解雇。因此,考虑到可能间隔太大,我将其设置为 1 以查看它是否与时间有关。如您所见,它仍然对我不起作用。
  • 那是一毫秒,它可以迅速将颜色变为红色并变回黑色,速度如此之快,你没有注意到。
  • @akatakritos,无论时机如何,我都调试了程序以确保实际调用了它的事件。我用断点运行代码。我的程序从未遇到 TxTimerEvent 的断点。
  • Transmit 是在与调用构造函数的线程不同的线程上调用的吗?

标签: .net winforms timer delphi-prism oxygene


【解决方案1】:

对于像“Transmit”和“Receive”这样的方法名称,很可能涉及到一个线程。就像运行 SerialPort 的 DataReceived 事件的线程池线程一样。或者由于 System.Timers.Timer 的 Elapsed 事件而运行的代码。等等。

在这样的工作线程中将 System.Windows.Forms.Timer 的 Enabled 属性设置为 true 是行不通的,它不是线程安全的类。它做它通常做的事,创建一个隐藏窗口,它使用 Windows 的 SetTimer() 方法来触发 Tick 事件。但是该窗口是在不发送消息循环的线程上创建的。所以 Windows 不会生成 WM_TIMER 消息。

根据需要使用 Control.Begin/Invoke() 以确保与计时器或控件相关的任何代码在 UI 线程上运行。

【讨论】:

  • 嗨 - 我可以将 Transmit 和 Receive 方法分别命名为 BigBird 和 Elmo。 :) 但是,我没有与我的TSerialIndicator 类本身关联的后台线程,尽管标签已添加到 UI 或主 winform。如您所知,我确实有一个用于串行端口通信的后台线程。我将不得不尝试您的建议。
  • 你是对的。如果您使用 System.Windows.Form.Timer,则应在 winform 上添加或使用它。如果您只想让计时器以特定的时间间隔重复执行某些操作,那么您可以使用 System.Timers.Timer。否则,您将不得不 Control.invoke/Begin 计时器的代码在 UI 线程中运行。所以,我继续将我的计时器更改为 System.Timers.Timer 并且它按预期工作。谢谢你,汉斯和其他人。
猜你喜欢
  • 1970-01-01
  • 2017-03-31
  • 2020-10-27
  • 2018-02-15
  • 2018-06-23
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
  • 2022-11-19
相关资源
最近更新 更多