winforms 计时器停止,但显然无法结束回调循环

qcbq4gxm  于 7个月前  发布在  其他
关注(0)|答案(3)|浏览(101)

我有这个定时器读取文本框值每1秒.一旦系统读取值,定时器理应停止和改变标签值.离开后,定时器,它应该继续处理我的其他逻辑.但显然它卡在timer_tick循环.
我试着用断点来追踪这个问题。注意,在程序点击return;之后,它转到了一个回调函数,并卡在了循环中。

private void Form1_Load(object sender, EventArgs e)
 {
    if (m_blnReset)
    {
     this.PickNoteTimer();
    }

    //other logics
 }

 private void PickNoteTimer()
 {
    this.ReadPickNoteTimer = new System.Windows.Forms.Timer { Interval = 1000 };
    this.ReadPickNoteTimer.Tick += new EventHandler(PickNoteTimer_Tick);
    this.ReadPickNoteTimer.Start();
 }

 private void PickNoteTimer_Tick(object sender, EventArgs e)
 {
    if (!string.IsNullOrEmpty(txtBoxPicknoteNumber.Text))
    {
      this.m_Picknote = txtBoxPicknoteNumber.Text.ToString();
      this.GetPickNoteDetails();

      if (this.ReadPickNoteTimer.Enabled)
         this.ReadPickNoteTimer.Stop();
      else
         return;
    }
}

private void GetPickNoteDetails()
{
   this.ReadPickNoteTimer.Stop();

   //logics to update value on label

 }
}

字符串

4sup72z8

4sup72z81#

一个可能的问题是,您正在停止PickNoteTimer_Tick方法和GetPickNoteDetails方法中的计时器。您应该从GetPickNoteDetails方法中删除this.ReadPickNoteTimer.Stop();调用,因为那里不需要它。当条件if (!string.IsNullOrEmpty(txtBoxPicknoteNumber.Text))满足时,应该停止PickNoteTimer_Tick方法中的计时器。
下面是更新后的代码:

private void PickNoteTimer_Tick(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(txtBoxPicknoteNumber.Text))
    {
        this.m_Picknote = txtBoxPicknoteNumber.Text;
        this.GetPickNoteDetails();

        if (this.ReadPickNoteTimer.Enabled)
            this.ReadPickNoteTimer.Stop();
    }
}

private void GetPickNoteDetails()
{
    // Logics to update value on label
    // You don't need to stop the timer here
}

字符串
如果您仍然面临计时器卡住的问题,那么您的应用程序中可能有其他一些因素可能会导致问题。

edqdpe6u

edqdpe6u2#

我的建议是将计时器创建代码移到构造函数中:

private readonly Timer readPickNoteTimer ;
public MyForm(){

    InitializeComponents();
    this.readPickNoteTimer = new System.Windows.Forms.Timer { Interval = 1000 };
    this.readPickNoteTimer.Tick += PickNoteTimer_Tick;
}
private void Form1_Load(object sender, EventArgs e)
{
    if (m_blnReset)
    {
        this.readPickNoteTimer .Start();
    }
}

字符串
有一个创建计时器的方法意味着这个方法可能被多次调用。这可能会导致多个计时器对象,这意味着第一个创建的计时器不再被引用,也不能被停止。
理论上,计时器应该有一个终结器,一旦它不再被引用,它最终会停止它,但是终结器在运行之前可能需要任意长的时间。它也可能进行一些全局注册,以防止收集。我不确定确切的行为。
确保只创建一个计时器对象应该可以避免这个可能的问题。如果你愿意,你仍然可以多次启动和停止计时器。即使它不能解决这个问题,它也可能是一个很好的实践。

nhhxz33t

nhhxz33t3#

只是一个想法:有时候,当一个尝试的解决方案导致其自身的问题时,值得花点时间问问这是否是一个正确的方法。这就是所谓的X-Y Problem概念。
在经历了多次类似的问题后,我决定采用一种“定时更新”的方法,这种方法不依赖于计时器来确定时间间隔,而是使用Task.Delay来做同样的事情,而不会那么麻烦。这是一种你可以尝试的替代方法:

public partial class MainForm : Form
{
    public MainForm() => InitializeComponent();
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        numericUpDown.ValueChanged += (sender, e) => 
        { 
            textBoxTitle.Clear();
            textBoxText.Clear(); 
        };
        _ = execTimerLoop();
    }

    private async Task execTimerLoop()
    {
        Cancel = new CancellationTokenSource();
        do
        {
            // Update title bar ~ every second or so
            Text = DateTime.Now.ToString(@"hh\:mm\:ss tt");

            getPickNoteDetails();
            await Task.Delay(TimeSpan.FromSeconds(1));
        } while (!Cancel.IsCancellationRequested);
    }

    CancellationTokenSource? Cancel { get; set; }
    .
    .
    .
}

字符串

示例

这个例程每秒轮询一次左边的控件,并且用当前时间更新标题栏文本。


的数据

private void getPickNoteDetails()
    {
        var selectionFontB4 = richTextBox.Font;
        var selectionColorB4 = richTextBox.SelectionColor;
        richTextBox.Clear();

        richTextBox.SelectionFont = new Font(selectionFontB4.FontFamily, 14F, FontStyle.Bold);
        richTextBox.SelectionColor = Color.FromArgb(0x22, 0x22, 0x22);
        richTextBox.AppendText($"{numericUpDown.Value}");

        if(!string.IsNullOrWhiteSpace(textBoxTitle.Text) ) 
        {
            richTextBox.SelectionFont = new Font(selectionFontB4.FontFamily, 12F, FontStyle.Bold);
            richTextBox.SelectionColor = Color.CadetBlue;
            richTextBox.AppendText($" : {textBoxTitle.Text.ToUpper()}");
            richTextBox.AppendText(Environment.NewLine);
        }

        richTextBox.SelectionFont = selectionFontB4;
        richTextBox.SelectionColor = selectionColorB4;
        richTextBox.AppendText($"{textBoxText.Text}");
        richTextBox.AppendText(Environment.NewLine);
    }

相关问题