解决异常:公共语言运行时检测到无效的程序
我碰到这个问题比较奇怪,我写的一个方法(基于.NET 2.0)在win7、win2003下运行没有问题,在winxp下运行就抛异常:“公共语言运行时检测到无效的程序”,对应英文为:common language runtime detected an invalid program.
抛异常的方法代码摘抄如下:
private Control control = ...; public void ActionOnUI<T1>(bool showMessageBoxOnException, bool beginInvoke, CbGeneric<T1> method, params object[] args) { if (this.control.InvokeRequired) { if (beginInvoke) { this.control.BeginInvoke(new CbGeneric<bool, bool, CbGeneric<T1>, object[]>(this.ActionOnUI), showMessageBoxOnException, beginInvoke, method, args); } else { this.control.Invoke(new CbGeneric<bool, bool, CbGeneric<T1>, object[]>(this.ActionOnUI), showMessageBoxOnException, beginInvoke, method, args); } } else { try { method((T1)args[0]); } catch (Exception ee) { if (showMessageBoxOnException) { MessageBox.Show(ee.Message); } } } }
方法的目的是对UI调用转发做一个封装,让使用者更方便的将调用转发到UI线程。
但是,这个方法在执行时,异常在xp下发生了:
Common Language Runtime detected an invalid program.
at ESBasic.Helpers.UiSafeInvoker.ActionOnUI[T1](Boolean showMessageBoxOnException, Boolean beginInvoke, CbGeneric`1 method, Object[] args)
我在网上搜了一些相关问题的解答,比较靠谱的一点是这样说的:
“这种错误非常少见,是一个编译器错误,通常产生在将C#等托管语言生成为MSIL时候出的错,没有什么好的解决办法,现在可行的方法好像就是修改现在的程序结构,这样根据新的结构生成新的MSIL时不会出错就基本可以避免这个问题。”
根据这个提示,我对方法的代码进行了各种修改尝试,最后终于得到了一种在xp下也不抛异常的结构,粘贴如下:
private Control control = ...; public void ActionOnUI<T1>(bool showMessageBoxOnException, bool beginInvoke, CbGeneric<T1> method, T1 args) { if (this.control.InvokeRequired) { if (beginInvoke) { this.control.BeginInvoke(new CbGeneric<bool, CbGeneric<T1>, T1>(this.Do_ActionOnUI<T1>), showMessageBoxOnException, method, args); return; } this.control.Invoke(new CbGeneric<bool, CbGeneric<T1>, T1>(this.Do_ActionOnUI<T1>), showMessageBoxOnException, method, args); return; } this.Do_ActionOnUI<T1>(showMessageBoxOnException, method, args); } private void Do_ActionOnUI<T1>(bool showMessageBoxOnException, CbGeneric<T1> method, T1 args) { try { method(args); } catch (Exception ee) { if (showMessageBoxOnException) { MessageBox.Show(ee.Message); } } }
总结起来,改变的几点如下:
(1)将真正执行的部分重构为一个方法Do_ActionOnUI,然后,转发调用Invoke都指向这个方法。
(2)Invoke转发调用时,为指向的方法加上泛型参数,避免编译器自动去匹配。
(3)将弱类型的参数object[]修改为强类型的参数T1。
好吧,现在问题总算是解决了,好好折腾了一番啊~~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
2008-10-23 DataRabbit 3.1发布,完全支持SqlServer2005/2008