多UI线程WPF程序随机挂起问题

来源:互联网 发布:照片恢复软件下载 编辑:程序博客网 时间:2024/06/05 18:33

问题描述

一个使用C#开发的程序,在某台Windows10,总是随机挂起,1天总有3、4次。主界面突然就挂起在任务栏里,无法使用,只有杀掉重新启动。具体什么操作造成的不能判断,因为都是在操作其它程序后,准备切换回来时才发现问题的。

实地查看

先查看了程序本身的日志,发现还是有线程记录日志输出,这说明进程还是活着的。UI主线程没有日志输入,初步判断问题在UI主线程。
然后使用了GDIView和SPY++工具来做进一步来诊断。
使用GDIView可以查看窗体的GDI句柄数目,Windows程序,GDI句柄数目如果过多,界面会僵住。查看下来,这个程序的GDI句柄数只有200多,不是句柄数目过多问题。
使用SPY++,能定位到程序窗口。选中这个窗口,点击右键菜单“消息”,发现居然还有WM_开头的消息出来。既然能够接受Windows消息,说明消息循环和主线程都健在。
综合前面2者,应该还是程序UI部分的问题了。

那具体什么原因造成的呢?暂时没有头绪。

网上搜索

于是,就网上搜索类似情况。找到2个链接。
https://www.devexpress.com/Support/Center/Question/Details/T235617
https://www.devexpress.com/Support/Center/Question/Details/B223292

文中提到可能跟多UI线程有关。本程序的确使用了多UI线程。
使用多UI线程生成窗体的代码是

Thread thread = new Thread(new ThreadStart(new Action(() =>{    WindowTemp newTempWindow = new WindowTemp();    newTempWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;    newTempWindow.ShowDialog();})));thread.SetApartmentState(ApartmentState.STA);thread.Start();

参考网上 http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/

修改为

Thread thread = new Thread(new ThreadStart(new Action(() =>{    WindowTemp newTempWindow = new WindowTemp();    newTempWindow.WindowStartupLocation = WindowStartupLocation.CenterScreen;    newTempWindow.Show();    newTempWindow.Closed += (s, e) =>         newTempWindow.Dispatcher.BeginInvokeShutdown(DispatcherPriority.Background);    Dispatcher.Run();})));thread.SetApartmentState(ApartmentState.STA);thread.Start(); 

然后在前面那台Windows10上测试,跑了1周,没有再出现挂起。

写在后面

对于Windows应用程序,UI部分还是放在主线程里更安全。
针对本例中使用多线程的原因,可以考虑不使用UI多线程,而是换种方式来解决。本例中,因为需要同时显示主窗体和会话窗体,这时候,如果其中窗体弹出一个模式对话框(ShowDialog()),那么另外一个窗体也被阻塞了。
可以参考的解决办法是不要用ShowDialog,使用Form的TopMost属性来模拟ShowDialog功能。
参看 http://stackoverflow.com/questions/2080968/c-sharp-pin-a-form-to-the-deskop。

0 0
原创粉丝点击