我在显示启动表单的方式上遇到了一个奇怪的问题,这会导致抛出InvalidAsynchronousStateException 。
首先,这里是我启动启动表单的 Main{} 代码:
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread splash = new Thread(new ThreadStart(ShowSplash));
splash.Start();
Application.Run(new MainForm());
}
static void ShowSplash()
{
using (SplashForm splash = new SplashForm())
{
Application.Run(splash);
}
}
我正在使用 .NET2.0 和 Win XP。
在应用程序运行了 5 个小时的一些测试中,我注意到异常的数量偶尔会增加一两个。(PerfMon 获得的数字,查看“# of Exceps Thrown”计数器。)这些异常似乎被运行时捕获和吞噬,因为它们不会引起波动并导致应用程序本身出现任何问题。至少无论如何我都无法确定。
我发现当系统触发 UserPreferenceChanged 事件时会引发异常。既然发现了这一点,我就可以通过改变背景图片或者屏保等随意产生异常。
我自己并没有在代码中的任何地方明确订阅此事件,但我了解(通过 Google 的力量)所有顶级控件和表单都会自动订阅此事件。
我还没有确定为什么这个事件首先被触发,因为它似乎发生在应用程序运行过夜时,但我想这是另一个有待解决的谜团。
现在,如果我停止运行启动表单线程,异常就会消失。运行线程,它回来了。那么,似乎某些事情并没有取消订阅该事件,这可能导致随后的异常?
有趣的是,如果我用默认的开箱即用表单替换我的初始表单,问题仍然存在:
static void ShowSplash()
{
using (Form splash = new Form())
{
Application.Run(splash);
}
}
在显示此表单时,任何 UserPreferenceChanged 事件都不会导致任何异常。一旦表单关闭,线程退出,就会抛出异常。
进一步的研究使我找到了这篇 Microsoft 文章,其中包含以下评论:
常见原因是在辅助 UI 线程上创建的闪屏或在工作线程上创建的任何控件。
嗯,从外观上看是有罪的。请注意,我的应用程序并没有冻结或做任何不愉快的事情。
目前,这更像是一种好奇心,但我担心将来这里可能会有一些隐藏的讨厌鬼等着咬。
对我来说,Application.Run 启动的表单或消息泵在终止时似乎没有正确清理。
有什么想法吗?