我正在制作一个日历应用程序供我自己使用和学习。
到目前为止,我已经毫无困难地使用多种形式,并在彼此之上打开新的等等。
以下是一个例子:
private void button1_Click(object sender, EventArgs e)
{
if (ceForm != null) ceForm.Close();
ceForm = new CalendarEventForm();
ceForm.Show();
}
无论如何,我现在开始添加计时器,以便在我日历上的重要事件发生之前弹出一个“提醒”表格(即等一小时等)。
代码在加载程序时设置定时器,然后在每个定时器过去时,这称为:
static void lazyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
mainForm.ShowReminder((sender as LazyTimer).ReferredEvent);
}
LazyTimer与System.Timers.Timer完全相同,除了添加的属性“ReferredEvent”,它引用了要提醒的日历事件。
MainForm.ShowReminder()如下:
public void ShowReminder(LazyEvent lazyEvent)
{
ReminderForm newReminder = new ReminderForm();
newReminder.LoadEvent(lazyEvent);
newReminder.Show();
}
奇怪的是ReminderForm崩溃了。我已经尝试过其他形式(例如CalendarEventForm,我知道它可以正常工作)并且它们也会崩溃。但是,当我尝试通过按下主窗体上的按钮来加载ReminderForm时,它可以正常工作。
为什么我的表单在被计时器(间接)加载时会崩溃?
答案 0 :(得分:9)
简答:使用System.Windows.Forms.Timer
,而不是System.Timers.Timer
。
原因是System.Timer.Timers
类将在另一个线程上触发timer事件,并且您无法直接从主UI线程之外的其他线程执行UI操作。
答案 1 :(得分:6)
如果它正在包装System.Timers.Timer
,它将在线程池线程上触发,这意味着你无法在那里进行UI操作。
改为使用System.Windows.Forms.Timer
,或将System.Timers.Timer
中的SynchronizingObject设置为UI对象,以便在UI线程上触发计时器。
Tick
事件处理程序,以这种方式捕获相关事件,从而避免额外的类和< / em>额外的方法:
// Presumably we've got a local variable here, e.g. currentEvent
timer.Tick += delegate { mainForm.ShowReminder(currentEvent; };
答案 2 :(得分:0)
您遇到了线程问题。
使用System.Windows.Forms.Timer
时请使用System.Windows.Forms
。
System.Timers.Timer
不会在应用程序事件循环上调用事件,而是直接调用事件处理程序,在您的情况下,这导致表单不支持的跨线程操作,并且您的应用程序崩溃。
相比之下,System.Windows.Forms.Timer
将无缝地融入System.Windows.Forms
的组件模型中。