把最近踩的坑总结一下(2)——二级MSoffice题库软件自动更新版本V2.0

     软件第一次能够正常运行,可是第二次只在任务管理器的进程菜单中出现应用程序的进程名称,并且主界面也没法显示。编程

        这个问题至关诡异,以致于开始的很长时间里不知道问题出在哪。在win7测试机上具体表现为:双击软件快捷方式后第1次界面能够显示,若是退出软件再启动时就没有任何反应,再次双击图标弹出重复运行警告。由于代码作了重复运行检测,说明程序已经运行,可是界面呢?为何没有界面?也没有异常提示。打开任务管理器,程序集名称安静的在进程列表里躺着,岁月静好。真是见鬼了,手动干掉进程,再来。依然如此,没有任何界面。在本身的开发机上运行一切正常,主界面正常显示,更新提示能够正常弹出。在另外的一台win7和win8机器上这个问题时有时无。安全

        没办法,首先百度。还真有人碰到相似的问题,任务管理器里有进程,界面不显示。认真看了一下他的问题描述及解决办法,缘由是在界面构造函数调用初始化函数时,目标机器上没有对应字体,形成控件渲染不下去,程序直接停在那里。对照他的解决办法对本身程序的控件初始化函数进行单步调试,一切正常,没有问题。并且,个人问题是界面有时能够出现,有时没法出现,因此应该不是界面初始化的问题。虽然这个答案对我解决问题没有帮助,可是贴主解决问题的思路值得学习,并且他程序有完整的日志功能,能够帮助分析解决问题,而个人程序根本没有日志功能。异步

        在开发机上调试运行时,功能正常,可是会出现System.InvalidOperationException类型的异常,提示线程间操做无效,从不是建立控件“FrmUkeMain”的线程访问它。解释一下,“FrmUkeMain”是个人主界面类,在主界面的Load事件中,使用了一个委托的BeginInvoke函数异步执行检查是否有可用的版本更新,使用回调函数的方式来显示结果,若是能够更新就弹出一个提示更新的窗口。由于使用MessageBox显示有时会被主界面挡住,用户稍不注意就看不见这个更新提示。因此我把这个提示作成了一个窗口,而后以showDialog的方式显示出来。通常状况下,若是窗口以showDialog的方式显示,会阻止调用窗口的消息响应,只有弹出窗口结束,调用窗口才能继续工做。只是这一次,虽然提示窗口显示正常显示出来,可是主窗口依然能够继续响应消息。(真是见鬼了,我当时压根没注意到弹出窗口和主窗口根本不在一个线程。)若是主窗口能够继续响应,那么弹出窗口仍然可能会被阻挡,问题依然存在。查看帮助文档发现showDialog还有一个重载方法,能够“将窗体显示为具备指定全部者的模式对话框”,这个方法也许管用。而后我就将主窗口的this引用传给了showDialog方法,再次运行达到预期效果。只是在调试时总会出现一开始所说的异常,而后我又按照网上的方式这个把窗体的CheckForIllegalCrossThreadCalls属性改成false,这样就不会用这个出现这个异常了。这里提示一下,正是从传this引用到关闭跨线程调用的异常检查这一系列的动做,才形成了后面的问题。因此说,有异常就要完全解决,不要使用这种掩耳盗铃的解决方法。函数

       好了,在开发机上这一套动做下来,没有异常了,功能运行也正常,一切看似很完美。可是,在测试机器上界面时有时无。何解?在开发机上调试也没有什么眉目。最后没办法,索性把项目文件放到测试机器上调试。将断点设置在showDialog(this)调用的位置,而后单步执行。主界面能够弹出,可是一片空白,没有控件显示,也没有异常出现。来来回回试了几回都是这样,也没找到问题缘由。最后索性不打断点,直接F5启动,跟以前同样窗口无显示,没有任何东西出现,就好像程序没有运行同样,可是任务管理器有承载进程。就这样等了一会,而后弹出这个下面这个窗口:学习

        “上下文切换死锁”,这是什么鬼?对CLR运行机制不太了解,可是隐隐感受到应该是异步调用出了问题。先把异步调用代码注释掉,再次运行,窗口能够正常显示,除更新意外的其余功能正常,因此问题就位于异步调用代码中。异步调用代码中可能引发死锁的应该就是那个主窗口的this引用,把this引用去掉,而后开启异步功能。此次主窗口能够正常显示,除了更新提示窗口可能被遮挡外功能都正常。看来这个主窗口的this引用就是引发死锁的元凶了。至于为何会引发死锁,应该和我在窗体的Load事件中使用异步并传入主窗体的this引用有关。其实以前编程中遇到控件跨线程调用,在调试时报异常,可是运行的时候通常能够正常运行,因此一开始也没当回事。如今算是给个提醒了,仍是不要跨线程调用,非要在跨线程调用的话仍是使用安全的方式,好比委托。测试

        好了,既然问题找到了,那就想办法解决。不使用委托的BeginInvoke方法来实现异步检查更新,改用BackgroudWorker类来实现,这样就不存在跨线程调用主线程控件的问题了。字体

       PS:在出现ContextSwitchDeadlock这个问题的时候,我在百度经验上看到一个解决办法是——将“调试”异常设置里的“ContextSwitchDeallock”这个异常引起设置选项不选中。呃。。。这真是一个眼不见心不烦的解决办法。这让我想到那句话:既然咱们没法解决问题,那么咱们就解决提出问题的人。this

相关文章
相关标签/搜索