C# 奇怪的Winforms Bug?

C# 奇怪的Winforms Bug?,c#,winforms,C#,Winforms,我正在制作一个日历应用程序供自己使用和学习 到目前为止,我还没有遇到过多个表单的问题,以及在彼此之上打开新表单等 下面是一个例子: private void button1_Click(object sender, EventArgs e) { if (ceForm != null) ceForm.Close(); ceForm = new CalendarEventForm(); ceForm.Show(); } 无论如何,我现在开始添加计时器,以便在日历上的重要事件

我正在制作一个日历应用程序供自己使用和学习

到目前为止,我还没有遇到过多个表单的问题,以及在彼此之上打开新表单等

下面是一个例子:

private void button1_Click(object sender, EventArgs e)
{
    if (ceForm != null) ceForm.Close();
    ceForm = new CalendarEventForm();
    ceForm.Show();
}
无论如何,我现在开始添加计时器,以便在日历上的重要事件发生之前(例如,1小时之前)弹出“提醒”窗体

该代码在加载程序时设置计时器,然后在每个计时器过期时,称为:

static void lazyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    mainForm.ShowReminder((sender as LazyTimer).ReferredEvent);
}
LazyTimer与System.Timers.Timer完全相同,只是添加了属性“referedEvent”,它指的是要提醒的日历事件

MainForm.show提醒如下:

public void ShowReminder(LazyEvent lazyEvent)
{
    ReminderForm newReminder = new ReminderForm();
    newReminder.LoadEvent(lazyEvent);
    newReminder.Show();
}
奇怪的是,RemindePerform崩溃了。我也尝试过其他表单,比如CalendarEventForm,我知道它正常工作,但也会崩溃。但是,当我试图通过按下主窗体上的按钮来加载提醒执行时,它工作正常

为什么我的表单在由计时器间接加载时会崩溃?

如果它正在包装System.Timers.timer,它将在线程池线程上启动,这意味着您无法在那里执行UI操作

改为使用System.Windows.Forms.Timer,或将System.Timers.Timer中的设置为UI对象,以便计时器在UI线程上启动

编辑:另一点。。。就我个人而言,我可能会使用lambda表达式或匿名方法作为计时器的Tick事件处理程序,以这种方式捕获相关事件,从而避免额外的类和额外的方法:

// Presumably we've got a local variable here, e.g. currentEvent
timer.Tick += delegate { mainForm.ShowReminder(currentEvent; };
如果它正在包装System.Timers.Timer,它将在线程池线程上启动,这意味着您不能在那里执行UI操作

改为使用System.Windows.Forms.Timer,或将System.Timers.Timer中的设置为UI对象,以便计时器在UI线程上启动

编辑:另一点。。。就我个人而言,我可能会使用lambda表达式或匿名方法作为计时器的Tick事件处理程序,以这种方式捕获相关事件,从而避免额外的类和额外的方法:

// Presumably we've got a local variable here, e.g. currentEvent
timer.Tick += delegate { mainForm.ShowReminder(currentEvent; };
简短回答:使用,而不是System.Timers.Timer

原因是System.Timer.Timers类将在另一个线程上触发计时器事件,并且您不能从主UI线程以外的其他线程直接执行UI操作。

简短回答:使用,而不是System.Timers.Timer


原因是System.Timer.Timers类将在另一个线程上触发计时器事件,并且您无法从主UI线程以外的其他线程直接执行UI操作。

您遇到了线程问题

使用System.Windows.Forms时,请使用System.Windows.Forms.Timer

System.Timers.Timer不会调用应用程序事件循环上的事件,而是直接调用事件处理程序,这会导致表单不支持的跨线程操作,从而导致应用程序崩溃


相反,System.Windows.Forms.Timer将无缝地融入System.Windows.Forms的组件模型。

您遇到了线程问题

使用System.Windows.Forms时,请使用System.Windows.Forms.Timer

System.Timers.Timer不会调用应用程序事件循环上的事件,而是直接调用事件处理程序,这会导致表单不支持的跨线程操作,从而导致应用程序崩溃


相反,System.Windows.Forms.Timer将无缝地安装到System.Windows.Forms的组件模型中。

为便于将来参考,为避免依赖心理调试器,它崩溃的帮助远不如它崩溃的帮助,但有以下例外:X.为便于将来参考,为避免依赖心理调试器,它崩溃的帮助远不如它崩溃的帮助,但有以下例外:X。