zoukankan      html  css  js  c++  java
  • Silverlight 操作Excel 中的进程资源释放问题(续)

    在前几天写到的Silverlight 操作Excel 中的进程资源释放问题 中,存在很多不完善的地方,因为在BeforeClose中处理掉Excel资源,会造成Excel无法再进行与代码的部分控制进行交互了。

    于是,继续谷歌……发现一篇很不错的文章,其Demo的效果也正是我想要的,于是,Mark一下。

    原文是日语的,借助翻译还是能看懂吧:(

    原问题的地址是:How to release COM objects in Silverlight 4,作者地址:http://csfun.blog49.fc2.com/blog-entry-79.html (好像要用代理才能看),Demo下载地址:SilverOffice

    以下是根据我个人的理解,翻译并整理的两个关键的类。

    1、ComObjectWrapper,实现IDisposable接口

     1  public class ComObjectWrapper : IDisposable
     2     {
     3         /// <summary>
     4         /// Com对象被释放时的事件
     5         /// </summary>
     6         internal event EventHandler ComObjectDisposed;
     7 
     8         //对象是否被释放
     9         private Boolean _disposed = false;
    10 
    11         /// <summary>
    12         /// Com对象集合
    13         /// </summary>
    14         private List<ComObjectWrapper> _children = new List<ComObjectWrapper>();
    15 
    16         /// <summary>
    17         /// Com对象是否被释放的的标记
    18         /// true情况下释放出来
    19         /// </summary>
    20         public Boolean Disposed
    21         {
    22             get
    23             {
    24                 return _disposed;
    25             }
    26         }
    27 
    28         /// <summary>
    29         /// 增加对象到集合,并为对象绑定释放事件
    30         /// </summary>
    31         /// <param name="child"></param>
    32         protected void AddChildren(ComObjectWrapper child)
    33         {
    34             _children.Add(child);
    35             child.ComObjectDisposed += new EventHandler(child_ComObjectDisposed);
    36         }
    37 
    38         /// <summary>
    39         /// 子对象被释放时在集合移除
    40         /// </summary>
    41         /// <param name="sender"></param>
    42         /// <param name="e"></param>
    43         private void child_ComObjectDisposed(object sender, EventArgs e)
    44         {
    45             _children.Remove(sender as ComObjectWrapper);
    46         }
    47 
    48         /// <summary>
    49         /// 释放Com对象(集合所有对象)
    50         /// </summary>
    51         private void ReleaseChildren()
    52         {
    53             foreach (ComObjectWrapper child in _children)
    54             {
    55                 child.ComObjectDisposed -= new EventHandler(child_ComObjectDisposed);
    56                 child.Dispose();
    57             }
    58 
    59             _children.Clear();
    60         }
    61 
    62         /// <summary>
    63         /// 执行释放资源(虚函数)
    64         /// </summary>
    65         protected virtual void DoDispose() { }
    66 
    67         #region IDisposable Members
    68 
    69         /// <summary>
    70         /// 释放Excel程序资源
    71         /// </summary>
    72         public void Dispose()
    73         {
    74             try
    75             {
    76                 //释放对象
    77                 ReleaseChildren();
    78 
    79                 DoDispose();
    80 
    81                 _disposed = true;
    82 
    83                 if (ComObjectDisposed != null)
    84                 {
    85                     ComObjectDisposed(this, EventArgs.Empty);
    86                 }
    87             }
    88             catch { }
    89         }
    90 
    91         #endregion
    92     }

    2、InstanceManager类,对所有Excel的Com对象进行管理

     1  public class InstanceManager
     2     {
     3         /// <summary>
     4         /// Excel对象实例集合
     5         /// </summary>
     6         private static List<ComObjectWrapper> _excelApplications = new List<ComObjectWrapper>();
     7 
     8         /// <summary>
     9         /// 新增一个Excel对象
    10         /// </summary>
    11         /// <returns></returns>
    12         public static ExcelApplication CreateAppication()
    13         {
    14             //自动化功能是否可用
    15             if (!AutomationFactory.IsAvailable) return null;
    16 
    17             dynamic excelObject = AutomationFactory.CreateObject("Excel.Application");
    18 
    19             ExcelApplication application = new ExcelApplication(excelObject);
    20             _excelApplications.Add(application);
    21             application.ComObjectDisposed += new System.EventHandler(application_ComObjectDisposed);
    22             return application;
    23         }
    24 
    25         /// <summary>
    26         /// Com对象被释放时的事件
    27         /// </summary>
    28         /// <param name="sender"></param>
    29         /// <param name="e"></param>
    30         static void application_ComObjectDisposed(object sender, System.EventArgs e)
    31         {
    32             try
    33             {
    34                 _excelApplications.Remove(sender as ComObjectWrapper);
    35             }
    36             catch { }
    37         }
    38 
    39         /// <summary>
    40         /// 取得已经运行的Excel进程实例。
    41         /// </summary>
    42         /// <param name="create"></param>
    43         /// <returns></returns>
    44         public static ExcelApplication GetApplication(bool create)
    45         {
    46             //自动化功能是否可用
    47             if (!AutomationFactory.IsAvailable) return null;
    48 
    49             dynamic excelObject = null;
    50 
    51             //在已经生成的com对象集合中取得没有被释放的实例
    52             foreach (ExcelApplication excel in _excelApplications)
    53             {
    54                 if (!excel.Disposed)
    55                 {
    56                     return excel;
    57                 }
    58             }
    59 
    60             try
    61             {
    62                 excelObject = AutomationFactory.GetObject("Excel.Application");
    63             }
    64             catch
    65             {
    66                 if (create)
    67                 {
    68                     excelObject = AutomationFactory.CreateObject("Excel.Application");
    69                 }
    70             }
    71 
    72             if (excelObject != null)
    73             {
    74                 ExcelApplication application = new ExcelApplication(excelObject);
    75                 _excelApplications.Add(application);
    76                 application.ComObjectDisposed += new System.EventHandler(application_ComObjectDisposed);
    77                 return application;
    78             }
    79             else
    80             {
    81                 return null;
    82             }
    83         }
    84 
    85         /// <summary>
    86         /// 释放所有Excel进程
    87         /// </summary>
    88         public static void ReleaseAll()
    89         {
    90             foreach (ComObjectWrapper wrapper in _excelApplications)
    91             {
    92                 wrapper.ComObjectDisposed -= new EventHandler(application_ComObjectDisposed);
    93                 wrapper.Dispose();
    94             }
    95             _excelApplications.Clear();
    96         }
    97     }

    使用时,在ExcelApplication的封装类进行调用Exit()函数即可。

    注意,封装类要进行继续1中的ComObjectWrapper类, 并重写DoDispose。封装类的代码就不上了,百度或者谷歌都有:(

    public class ExcelApplication : ComObjectWrapper
    {
    
        /// <summary>
       /// Excel程序退出 /// </summary> public void Exit() { _excel.Quit(); Dispose(); }   /// <summary> /// Com对象的释放处理 /// </summary> protected override void DoDispose() { try { Workbooks.Close(); Workbooks.Dispose(); _excel.Quit(); ((IDisposable)_excel).Dispose(); _excel = null; } catch { } }     //other code ........... }

    public class ExcelWorkbook : ComObjectWrapper
    {
      
    protected override void DoDispose() { try { ((IDisposable)workBook).Dispose(); } catch { } } //.................other code
    }

     11月27日补充:

    在手动new一个Excel封装类的变量后(如:ExcelWorkSheet、ExcelRange),一定要记得把它手动释放进程,不然会直到程序关闭才自动释放!

     var currentSheet = new ExcelWorkSheet {WorkSheet = workBook.WorkBook.ActiveSheet};
    // other code to do something
    currentSheet.Dispose();

     

    作者:Ivan
    个人网站:http://www.IvanBy.com
  • 相关阅读:
    JAVA关键字Volatile的特性
    深入理解JAVA虚拟机之JVM性能篇---垃圾回收
    深入理解JAVA虚拟机之JVM性能篇---基础知识点(运行时数据区域)
    Oracle Rac创建表空间及用户
    数据库的事务隔离(转)
    数据库的三大范式和五大约束(转)
    一些常用的操作命令及知识点
    基于tomcat+springMVC搭建基本的前后台交互系统
    MYSQL注入天书之开天辟地
    MYSQL注入天书之前言
  • 原文地址:https://www.cnblogs.com/oneivan/p/2789302.html
Copyright © 2011-2022 走看看