近期在定位问题时发现使用OleDb打开很大的Excel文件后,即使什么都不操作Colse掉,内存释放了部分,但是并未回到打开前的水平。在Excel 150M,解压缩后900M的场景下,打开后直接Close,内存比打开前多了近90M。如果再次打开关闭,内存不会再增加。但是如果是依此打开多个不同的大型Excel文件,程序很容易内存溢出崩掉。
在会用Red Gate进行内存分析时,发现确实是Excel非托管代码,在不断累积内存,想了很久,目前想到的有3种解决方案。

首先,先上问题复现的代码,很简单,就是使用OleDb打开一个150M左右的Excel

C# code

 

?

1
2
3
4
5
6
7
8
9
10
11
private static void Test()
        {
 Console.Read();
            using (var con=new OleDbConnection(string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source='{0}';Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'",@"F:/1.xls")))
            {
                con.Open();
                con.Close();              
            }
  GC.Collect();
 Console.Read();
        }

复现步骤:
1,准备一个150M的Excel
2,打开任务管理器,打开程序。
3,记录当前程序内存。
4,回车,等到文件读取完毕,并Close释放内存稳定后,再记录当前程序内存。
5,发现多处了70-90M

解决方案
1,经过验证,CSV类型,使用OleDb打开后没有出现类似的内存泄露。所以,可以先把xls、xlsx转为csv,再对csv使用oleDb打开进行操作,最后删掉该csv即可。
如果使用该方法需要注意,csv读取不能根据Sheet读取,只能读整个文件。
xls、xlsx的转化需要使用Microsoft.Office.Interop.Excel.Apllication ,所以需要把当前所需的数据库操作封装一层。

2,直接使用Microsoft.Office.Interop.Excel.Apllication进行Excel操作,并在操作后直接杀掉Excel进程。
但是该方法因为Microsoft.Office.Interop.Excel.Apllication进行Excel读取,每个Range每个Range的读取,都是进程间进行数据交换,性能太渣。唯一可行的是,一大块一大块的读数据,但是没有找到对应的方法。

3,另起一个进程,使用OleDb对Excel进行操作,操作后杀掉该进程。
这个方案可行度也不高,在C#下,要另起进程,带来的稳定性、性能开销都比较大,特别是如果是频繁读取Excel的场景下。

需要解决的问题
1,还有没有更好的办法,在不使用Microsoft.Office.Interop.Excel.Apllication的情况下,解决这一问题。因为使用Microsoft.Office.Interop.Excel.Apllication,就意味着要开个Excel进程,意味着性能开销。
2,OleDb在打开Excel文件时,会进行解压缩,150M 的文件,Open完毕后,程序进程能增加900多M。而使用Microsoft.Office.Interop.Excel.Apllication进行打开,发现只增加了150M。能否在使用OleDb的情况下,减小这部分的内存增加,要知道在程序本身就很耗内存的情况下,打开个Excel就陡增了900M,是很容易崩掉的。

以下是微软提供的解决办法
http://support.microsoft.com/kb/319998

OleDb 内存泄露问题的更多相关文章

  1. java: web应用中不经意的内存泄露

    前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...

  2. 查看w3wp进程占用的内存及.NET内存泄露,死锁分析

    一 基础知识 在分析之前,先上一张图: 从上面可以看到,这个w3wp进程占用了376M内存,启动了54个线程. 在使用windbg查看之前,看到的进程含有 *32 字样,意思是在64位机器上已32位方 ...

  3. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  4. 基于HTML5的WebGL应用内存泄露分析

    上篇(http://www.hightopo.com/blog/194.html)我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动, ...

  5. android:布局、绘制、内存泄露、响应速度、listview和bitmap、线程优化以及一些优化的建议!

    1.布局优化 首先删除布局中无用的控件和层级,其次有选择地使用性能较低的viewgroup,比如布局中既可以使用RelativeLayout和LinearLayout,那我们就采用LinearLayo ...

  6. js内存泄露的几种情况详细探讨

    内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束.在C++中,因为是手动管理内存,内存泄露是经常出现的事情.而现在流行的C#和Java等语言采用了自动垃圾回收方法管理内存,正常使 ...

  7. 使用Xcode7的Instruments检测解决iOS内存泄露

    文/笨笨的糯糯(简书作者)原文链接:http://www.jianshu.com/p/0837331875f0著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 作为一名iOS开发攻城狮, ...

  8. 使用Visual Leak Detector for Visual C++ 捕捉内存泄露

    什么是内存泄漏? 内存泄漏(memory leak),指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段 ...

  9. java内存溢出和内存泄露

    虽然jvm可以通过GC自动回收无用的内存,但是代码不好的话仍然存在内存溢出的风险. 最近在网上搜集了一些资料,现整理如下: —————————————————————————————————————— ...

随机推荐

  1. redis python-redis 安装详细步骤

    安装redis 把redis安装到 /opt/redis-2.8目录中 wget http://download.redis.io/releases/redis-2.8.1.tar.gz tar -z ...

  2. CVPR 2007 Learning to detect a salient object

    Dataset: MSRA A&B are introduced in this paper. A conditional Random Field based method was prop ...

  3. Linux C 开发环境配置

    换了新电脑,重装了Fedora10,所有开发环境都要重新配置啦,开个随笔记录下过程,说不定以后还要用~ 首先Fedora10装好之后是不带 VIM 的,果断安装之: 打开终端,首先 su 命令切换到r ...

  4. 因为此版本的应用程序不支持其项目类型(.csproj)”之解

    有的时候vs无缘无故的出现如下错误:"因为此版本的应用程序不支持其项目类型(.csproj),若要打开它,请使用支持此类型项目的版本" 解决办法:如果是这个提示,可能是由于你安装m ...

  5. 《转》iOS音频视频初级开发

    代码改变世界 Posts - 73, Articles - 0, Comments - 1539 Cnblogs Dashboard Logout HOME CONTACT GALLERY RSS   ...

  6. Reveal的使用及破解方法

    Reveal的使用其实真的很简单,就如第一张镇楼图的效果一样.中间是3D可视化当前APP页面的视图,左侧则是这些UI元素和层次结构,而右侧则是View的属性,你可以修改View的颜色.frame等等, ...

  7. 新学习到的vi的一些命令

    1.普通模式下.符号可以重复上次的命令 2.普通模式下n<command>可以重复n次command命令 3.dw可以删除单个词    dnw可以删除n个单词  x和X可以在普通模式下删除 ...

  8. 四、解决MyEclipse控制台输出中文乱码的问题

    问题描述:       在Java程序中,在MyEclipse开发环境下,通过标准输入输入中文,并把输入的中文信息从标准输出显示出来,这时中文出现乱码情况.解决方法:解决方法需要两个步骤(本文测试环境 ...

  9. h5 摄像头处理 在线视频

    http://www.360doc.com/content/08/0812/03/72059_1533104.shtml http://html5online.com.cn/articles/2012 ...

  10. matlab 连续读取多个文件

    方法1: 把文件的文件名按一定的规律命名,假如:filename1.txt,filename2.txt,...,fielname100.txt,在读取的时候则可以使用循环: for i = 1:100 ...