【问题标题】:c# Excel thread doesn't finish (FinalReleaseComObject)c# Excel 线程未完成 (FinalReleaseComObject)
【发布时间】:2016-08-28 06:39:57
【问题描述】:

我有一个读取 Excel 的功能,然后是工作簿和工作表。 但是 Excel 线程永远不会完成。我尝试了在这里找到的所有解决方案,但没有奏效。

任务管理器上的 Excel 线程堆栈,目前,我的应用程序由于 Excel 停止工作而崩溃。

    public static object[,] ReadFile(string filepath, string sheetname)
    {
        Application xlApp = null;
        Workbooks wks = null;
        Workbook wb = null;
        object[,] values = null;
        try
        {
            xlApp = new ApplicationClass();
            wks = xlApp.Workbooks;
            wb = wks.Open(filepath, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);
            Worksheet sh = (Worksheet)wb.Worksheets.get_Item(sheetname);

            values = sh.UsedRange.Value2 as object[,];


            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sh);
            sh = null;

        }
        catch (Exception ex)
        {
            throw new Exception(string.Format("Sheet \"{0}\" does not exist in the Excel file", sheetname));
        }
        finally
        {

            if (wb != null)
            {

                wb.Close(false);
                Marshal.FinalReleaseComObject(wb);
                wb = null;
            }

            if (wks != null)
            {
                wks.Close();
                Marshal.FinalReleaseComObject(wks);
                wks = null;
            }

            if (xlApp != null)
            {
                // Close Excel.
                xlApp.Quit();
                Marshal.FinalReleaseComObject(xlApp);
                xlApp = null;
            }


        }

        return values;
    }

也许我没有按正确的顺序做事,或者我对 COM 对象问题的理解有误。

【问题讨论】:

  • 你的应用在哪一行崩溃了?
  • 我必须阅读大量的 Excel 文件。因此,代码每次在“xlApp = new ApplicationClass();”上启动一个 Excel。我认为“xlApp.Quit();Marshal.FinalReleaseComObject(xlApp);xlApp = null;”足以计算 Excel。但 Excel 永远不会关闭。所以应用程序崩溃了,因为此刻,我有近 20 个 EXCEL.EXE 进程在后台运行。
  • FinalReleaseComObject 应该不是必需的。您正在为 excel 使用 .net 包装器。如果删除 FinalReleaseComObject 会发生什么?
  • 好的,尝试使用ReleaseComObject代替FinalReleaseComObject,这个问题在S.O.中暴露的次数更多:stackoverflow.com/questions/17367411/…,stackoverflow.com/questions/3937181/…
  • 正如我所说,我已经尝试了我在 SO 上看到的所有内容。 ReleaseComObject 不起作用,我尝试了“非两点” xlApp = new ApplicationClass(); wks = xlApp.Workbooks; wb = wks.Open(文件路径,丢失,丢失,丢失,丢失,丢失,丢失,丢失,丢失,丢失,丢失,丢失,丢失,丢失,丢失);工作表 = wb.Worksheets; sh = (工作表)sheets.get_Item(sheetname);它也没有工作......

标签: c# excel


【解决方案1】:

我遇到了同样的问题,我用下面的代码专门杀死了进程

[DllImport("user32.dll")]
    static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);

    Process GetExcelProcess(Excel.Application excelApp)
    {
        int id;
        GetWindowThreadProcessId(excelApp.Hwnd, out id);
        return Process.GetProcessById(id);
    }

此方法GetExcelProcess将为您提供可以手动终止的确切进程。它将从任务管理器中删除 Excel.exe。

【讨论】:

    【解决方案2】:

    据我了解,如果您使用 .NET 包装器对象(如 excel 互操作),则无需显式释放 com 对象。如果 excel 仍然存在,那么我会寻找处理中的错误,因为可能会留下一些东西。
    在下面的示例中,当涉及到第一个 console.ReadLine 时,excel 进程已经停止。如果它没有立即停止,请尝试按 Enter 启动 GC。

    以下对我有用,excel 已停止。
    我用过:
    .NET 框架 4.5.2
    Microsoft.Office.Interop.Excel 1.7.0.0
    Excel 2010
    视窗 7

    using System;
    using Microsoft.Office.Interop.Excel;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Go");
                var t = ReadFile(@"<filename>", "<sheetname>");
                Console.WriteLine("1");
                Console.ReadLine();
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                Console.ReadLine();
            }
    
    
            public static object[,] ReadFile(string filepath, string sheetname)
            {
                Application xlApp = null;
                Workbooks wks = null;
                Workbook wb = null;
                object[,] values = null;
                try
                {
                    xlApp = new Application();
                    wks = xlApp.Workbooks;
                    wb = wks.Open(filepath);
                    Worksheet sh = (Worksheet)wb.Worksheets.get_Item(sheetname);
    
                    values = sh.UsedRange.Value2 as object[,];
    
                    //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sh);
                    //sh = null;
    
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.WriteLine(string.Format("Sheet \"{0}\" does not exist in the Excel file", sheetname));
                }
                finally
                {
    
                    if (wb != null)
                    {
    
                        wb.Close(false);
                        //Marshal.FinalReleaseComObject(wb);
                        wb = null;
                    }
    
                    if (wks != null)
                    {
                        wks.Close();
                        //Marshal.FinalReleaseComObject(wks);
                        wks = null;
                    }
    
                    if (xlApp != null)
                    {
                        // Close Excel.
                        xlApp.Quit();
                        //Marshal.FinalReleaseComObject(xlApp);
                        xlApp = null;
                    }
    
    
                }
    
                return values;
            }
        }
    
    }
    

    作为对不使用两个点命令的链接 stackoverflow 问题的评论。该示例在我的机器上也可以使用两个点命令(打开工作簿)。这并没有什么不同。 Excel 已发布,该过程已关闭。用于测试的 excel 表是一个标准表,其中 3 个字段用数字填写。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 2013-12-10
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 2022-09-23
      相关资源
      最近更新 更多