【问题标题】:C# COM DLL is preventing VBA application from exitingC# COM DLL 阻止 VBA 应用程序退出
【发布时间】:2012-02-12 20:42:37
【问题描述】:

我创建了一个 C# COM DLL,它本质上是一个增强的进度条,在新线程上运行 System.Windows.Forms.Application.Run() 以显示带有对话框的表单。要在使用 VBA 的第三方应用程序中使用它,您可以执行以下操作:

Set pg = CreateObject("MyNS.MyProgressBar")
pg.ShowBar()
.
.
pg.Progress = 0.5
.
.
pg.ShutDownBar()

问题是用户能够在达到 pg.ShutDownBar() 之前关闭应用程序(使用 File->Quit 或类似方法)。如果用户这样做,pg.ShutDownBar() 永远不会被调用,结果是虽然应用程序的窗口被隐藏了,但它仍然出现在任务管理器进程中。

所以我的问题是: 有没有办法检测父应用程序是否已经关闭然后中止c#中进度条的线程?

我已经在启动对话线程的主线程上尝试了 System.Windows.Forms.Application.ThreadExit 和 System.Windows.Forms.ApplicationExit,但是在通过 COM 访问对象时似乎没有引发这些事件(尽管它们当我在 .NET 中创建对象时调用)....

谁能给点建议?

【问题讨论】:

  • 听起来像是典型的 DoEvents() 问题。不要使用它。
  • 没有代码调用 DoEvents()... 我尝试不使用 Application.Run 在单独的线程上启动我的对话框,而是在单独的线程上使用 form.ShowDialog(),但随后对话框基本上被冻结了......不知道为什么?
  • 如果在应用程序退出事件中将进度条对象设置为 Nothing 会发生什么?

标签: c# multithreading vba com


【解决方案1】:

这是 COM 引用计数工作方式的问题。除非调用您的 COM 包装器的程序释放引用(正如 M. Babcock 建议的那样,这将要求程序执行“设置 pg = Nothing”的步骤),否则您的进度条将无法正确关闭。

我能提出的唯一建议是设置一个“超时”属性(默认为 30 秒)。然后在进度条中使用后台线程,检查最后一次调用“pg.Progess”是多久以前,如果它>超时值,则关闭。这是假设您可以期望大多数 VB 脚本至少每 X 秒报告一次进度(其中 X 是超时值)。

【讨论】:

  • 是的!这行得通...我将窗口句柄发送到新线程,然后每隔几秒钟检查一次窗口句柄是否仍然有效。如果不是,那么它就关闭了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 2023-04-01
  • 2011-02-01
  • 1970-01-01
  • 2016-12-01
相关资源
最近更新 更多