Windows窗体计时器

本文关键字:计时器 窗体 Windows | 更新日期: 2023-09-27 18:26:23

我有两个windows窗体。我需要在每个调整后的时间间隔内打开第二张表格。第二个表单需要在指定的秒内显示。在主窗体中:

public static System.Timers.Timer reminderTimer = new System.Timers.Timer();
private static void ActiveteReminder()
{
    int duration = Reminder.Frequency;
    reminderTimer.Interval = duration;
    reminderTimer.Elapsed += new System.Timers.ElapsedEventHandler(reminderTimer_Elapsed);
    reminderTimer.AutoReset = false;
    reminderTimer.Start();
}
static void reminderTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    ReminderForm reminderForm = new ReminderForm();
    reminderForm.Show();
    if (Reminder.ReminderStatus == ReminderStatusEnum.ReminderStatus_Active)
        reminderTimer.Start();
    else
        reminderTimer.Stop();
}

第二种形式:

public System.Timers.Timer reminderTimer = new System.Timers.Timer();
private void ActivateTimer()
{
    int duration = Reminder.Duration;
    reminderTimer.Interval = duration;
    reminderTimer.AutoReset = false;
    reminderTimer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
    reminderTimer.Start();
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    reminderTimer.Dispose();
    this.Close();
}

我在尝试关闭第二个表单时出现以下错误:"跨线程操作无效:控件'reminderForm'是从在上创建的线程以外的线程访问的"

我该怎么解决这个问题?

Windows窗体计时器

这里的问题是您正在组合System.Timers.Timer和WinForms应用程序。Elapsed回调将发生在线程池线程上。从UI线程以外的任何线程与winforms元素通信都是非法的。因此,当你从回调中执行以下行时,你会得到一个异常

this.Close();

要解决此问题,只需使用System.Windows.Forms.Timer即可。这将在UI线程上引发其事件,并且可以避免任何跨线程通信。

您需要检查表单的InvokeRequired标志。这应该会告诉您需要了解的内容:http://msdn.microsoft.com/en-us/library/ms171728.aspx

您应该在UI线程中invke所有与UI相关的代码。你应该做的第一件事是删除所有静态单词

第一种形式

private void reminderTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
  Elapsed();  
}
private void Elapsed()
{
  if(InvokeRequired)
  {
    Invoke((Action)Elapsed);
    return;
  }
  ReminderForm reminderForm = new ReminderForm();
  reminderForm.Show();
  if (Reminder.ReminderStatus == ReminderStatusEnum.ReminderStatus_Active)
    reminderTimer.Start();
  else
    reminderTimer.Stop();
}

第二种形式

void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    Elapsed();
}
private void Elapsed()
{
  if(InvokeRequired)
  {
    Invoke((Action)Elapsed);
    return;
  }
  reminderTimer.Dispose();
  this.Close();
}