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'是从在上创建的线程以外的线程访问的"
我该怎么解决这个问题?
这里的问题是您正在组合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();
}