【问题标题】:Using BackgroundWorker will leave Excel process running after closing Excel使用 BackgroundWorker 将使 Excel 进程在关闭 Excel 后继续运行
【发布时间】:2014-11-26 21:13:04
【问题描述】:

我正在使用 C# 编写一个 Excel 加载项,该加载项在运行模拟时会显示进度条。我希望 BackgroundWorker 异步运行模拟并将进度报告回进度条表单。

模拟方法需要引用当前 Excel COM 应用程序。我有一个名为ThisAddin 的类,它实现了ExcelDna.Integration.IExcelAddIn 接口,并有一个返回应用程序的静态属性。

但是,一旦后台工作人员尝试以任何方式使用该应用程序,即使在我退出 Excel 后,它也会让 Excel 进程继续运行。

例如,如果我只是像这样在 Excel 应用程序中设置一个属性:

void backgroundworker_DoWork(object sender, DoWorkEventArgs e)
{
    ThisAddIn.App.DisplayStatusBar = true;
}

然后在运行加载项并关闭 Excel 后,我的任务管理器中仍然会运行一个 Excel 进程。

有没有办法确保进程被杀死?我是否以某种方式在后台工作人员中创建了另一个应用程序实例?我不明白,因为如果我从后台工作人员中调用应用程序上的 quit(),它将关闭整个应用程序,并且该进程仍将继续运行!

当后台工作人员完成时,我确保对其调用 dispose() 并中止其当前线程。我按照here 的建议使用了“AbortableBackgroundWorker”类。但这仍然不能解决我的问题。

【问题讨论】:

  • 解决问题的最简单方法是执行 BGW 的任务,仅访问 ProgressChanged 或 RunWorkerCompleted 事件处理程序的事件处理程序中的“UI”。正确放置的 GC.Collect() 是一种替代方法。

标签: c# multithreading excel backgroundworker excel-interop


【解决方案1】:

问题在于您持有 Excel 对象的时间比您想象的要长。我见过成功使用的两个选项:

  1. 在您触摸的每个 Excel 对象上使用 Marshal.ReleaseComObject。
  2. 创建一个新的 AppDomain 并在其中完成所有 Excel 工作。然后卸载整个 AppDomain,这样可以确保任何延迟对象都将被处理掉。

选项 1 更容易理解,但更脆弱且容易出错。

【讨论】:

  • 其实也有选项3。只需调用GC.Collect(),如果 GC 运行正常(它没有附加调试器),那么它将收集 com 对象并关闭 excel。调用GC.Collect() 来清理com 互操作对象是少数几个这样做的好主意之一。 (见this SO answer最后一段)
  • 啊,我试过GC.Collect(),但它不起作用,但我在调试模式下构建,所以也许这就是原因。
  • @Todd 它不仅需要处于发布模式,而且您需要在没有附加调试器的情况下执行此操作。调试器是更重要的部分。
  • @Scott Gotcha,感谢您明确表示。感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 2019-08-05
  • 2021-05-24
  • 2015-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2019-03-03
相关资源
最近更新 更多