Windows Forms Timers

2019-08-02 10:47发布

I have two windows forms. I need to open second form in each adjusted time intervals. And second form needs to show up during specified seconds. In mainForm:

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();
}

In second form:

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();
}

I got following error when trying to close second form : "Cross-thread operation not valid: Control 'reminderForm' accessed from a thread other than the thread it was created on"

How can I fix this?

3条回答
Anthone
2楼-- · 2019-08-02 11:08

You need to examine the form's InvokeRequired flag. This should tell you what you need to know: http://msdn.microsoft.com/en-us/library/ms171728.aspx

查看更多
乱世女痞
3楼-- · 2019-08-02 11:17

You should invke all UI related code in the UI thread. First thing wcith should you do is all static words removal

First form

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();
}

Second form

void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    Elapsed();
}

private void Elapsed()
{
  if(InvokeRequired)
  {
    Invoke((Action)Elapsed);
    return;
  }
  reminderTimer.Dispose();
  this.Close();
}
查看更多
不美不萌又怎样
4楼-- · 2019-08-02 11:22

The problem here is you are combining a System.Timers.Timer and a WinForms application. The Elapsed call back will occur on a thread pool thread. It's illegal to communicate with a winforms element from any thread but the UI thread. Hence when you execute the following line from the callback you get an exception

this.Close();

To fix this simply use a System.Windows.Forms.Timer instead. This will raise its events on the UI thread and you can avoid any cross thread communication.

查看更多
登录 后发表回答