我有一个函数来读取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对象问题。
答案 0 :(得分: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。
答案 1 :(得分:1)
根据我的理解,如果使用像excel interop这样的.NET包装器对象,则不必显式释放com对象。如果excel仍然存在,那么我会在处理中寻找错误,因为可能会留下一些东西 在下面的示例中,excel进程在第一个console.ReadLine时已停止。如果它没有立即停止尝试按Enter键启动GC。
以下为我和excel的工作已停止
我用过:
.NET Framework 4.5.2
Microsoft.Office.Interop.Excel 1.7.0.0
Excel 2010
Windows 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个字段填入数字。