c# - 从 WinForms GUI 线程调用 COM 线程上的方法时出现问题?

标签 c# .net winforms com com-interop

我在使用 .NET 编写的 COM 组件时遇到问题,抛出如下警告:

Context 0x15eec0 is disconnected. No proxy will be used to service the request on the COM component. This may cause corruption or data loss. To avoid this problem, please ensure that all contexts/apartments stay alive until the application is completely done with the RuntimeCallableWrappers that represent COM components that live inside them.

看起来这是由于我的 GUI 线程在 COM 线程中调用函数而没有必要的同步造成的。作为引用,我使用了 http://msdn.microsoft.com/en-us/library/ms229609%28VS.80%29.aspx 中设置的指南用于在 COM 组件中创建我的 GUI 线程。

我的代码看起来像这样:

class COMClass {
  // this is called before SomeMethod
  public void Init() {
    ComObject comObject = new ComObject(); // this is imported from a TLB

    // I create my GUI thread and start it as in the MSDN sample
    Thread newThread = new Thread(new ThreadStart(delegate() {
      Application.Run(new GUIForm(comObject));
    }));
  }

  public void SomeMethod(){
    comObject.DoSomething();               // this is where the error occurs
  }
}

class GUIForm : Form {
  ComObject com;
  public GUIForm(ComObject com) {comObject = com;}

  public void SomeButtonHandler(object sender, EventArgs e) {
    comObject.SomeMethod();  // call on the GUI thread but the com object is bound to the COM thread...
  }
}

是否有处理此问题的既定方法?调用 GUI 没问题(Invoke/BeginInvoke),但调用其他方式似乎更困难...

编辑:也不是以任何方式修改 COM 对象的选项。

最佳答案

从您的代码片段中看不太清楚最重要的 Init() 方法是如何调用的以及线程是如何启动的。显然,创建 COM 对象的线程与调用 SomeMethod() 的线程不同。进一步假设 COM 服务器是单元线程的,COM 需要将 SomeMethod() 调用编码到创建对象的线程。调用 Init() 的那个。如果该线程不再运行,就会发生欢闹。

有一个明显的问题,您忘记调用 Thread.SetApartmentState()。

鉴于 COM 已经编码线程间调用,您可能无法通过启动自己的线程获得任何好处。如果 COM 服务器拒绝支持多线程,您就无法神奇地使其成为多线程。

关于c# - 从 WinForms GUI 线程调用 COM 线程上的方法时出现问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2292477/

相关文章:

c# - 无法动态地将行添加到我的数据绑定(bind) dataGridview

vb.net - 如何在不创建新字体的情况下更改字体大小

c# - 如何使用 C# 访问 Outlook 用户的日历?

c# - 我应该在一般领域使用什么模式?

c# - EF lambda : How to fetch all data that match any id from a List

c# - 即使发生未处理的异常,也要保持应用程序运行

.net - 如何确保 Puppet 代理上安装了 .NET 4.5?

.net - 如何知道 DataGridView 的数据绑定(bind)何时*真正*完成?

c# - 如何处理 OutOfMemoryException 直到它不再抛出?

c# - 从表单中读取字符串作为逐字字符串,\\显示而不是\