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