记一次因内存不足导致的WPF程序闪退问题

报错:system.outofmemoryexception 
system.windows.media.composition.DUCE+channel.syncflush
system.windows.interop.hwndtarget.updatewindowsettings
system.windows.interop.hwndtarget.updatewindowspos
system.windows.interop.hwndsource.hwndtargetfiltermessage
ms.win32.hwndwrapper.wndproc
ms.win32.hwndsubclass.dispatchercallbackoperation

...............

这个问题在之前偶然出现,但最近非常频繁,在程序运行几个小时后就会出现界面卡顿,然后点击无响应,最后闪退的情况。

报错中带有Media字样,看上去很像媒体资源未释放导致的,可是我过了一遍确定代码里面的媒体文件处理是安全的。

看任务管理器,进程的句柄、线程数,也都在合理范围内。那会不会不是我代码问题呢?

于是照着前人总结的办法试一下:

 试这三个因为客户现场原因花了较多时间,均无效。看了下.NET版本,也是匹配的。

于是开始思索,内存不足,会不会是由于程序内存占用过多,挤占了界面的那一部分,于是这个报错里面才会带有Media类型?

换用VS调试模式运行,通过截取快照对比多个时刻的内存使用,看到内存变化也都是在预期内。

问题总是要解决,从业4年,到现在为止还没有处理不了的问题。

搬出最朴素扎实的办法:排除法。为不影响现场生产,我将程序拆成2个程序,一个程序做一部分动作,区分两个程序的操作设备部分,然后分别观察2个程序会不会闪退。

运行一天,一个程序闪退频率明显高于另一个,对比分析两边调方法的差异,定位分析可能有问题的代码,直到发现了这个(为保护公司信息,已删去业务相关代码,仅保留错误部分):


            IntPtr ptr = new IntPtr();
            while (m_bStart)
            {
                try
                {
                    调DLL方法
                    if (len > 0)
                    {
                        try
                        {
                            ptr = Marshal.AllocHGlobal((int)len * size);
                            调DLL方法
                        }
                        catch
                        {
                            Marshal.FreeHGlobal(ptr);
                        }
                        
                    }
            }

这段代码是在一个循环调库接收数据的线程里面的。

Marshal.AllocHGlobal 通过使用指定的字节数,从进程的非托管内存中分配内存。

Marshal.FreeHGlobal 释放以前从进程的非托管内存中分配的内存。

GC并不会强制管理非托管资源的释放。

可想而知,这段代码放在接收线程里面使用的非托管内存一定会越积越多。之前的程序员为什么会这样写?除了他谁也不知道。或许他是想将 FreeHGlobal 放到 finally 里面呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值