【发布时间】:2011-09-05 08:23:39
【问题描述】:
我正在使用来自第三方库的 COM 对象来生成周期性事件。当我使用 Winforms 应用程序中的库时,将对象作为类成员并在主窗体线程中创建它,一切正常。但是,如果我从另一个线程创建对象,我不会收到任何事件。
我的猜测是我需要在用于创建对象的同一个线程中有某种事件循环。
我需要从控制台应用程序中使用这个对象。我想我可以使用 Application.DoEvents,但我宁愿不在控制台应用程序中包含 Winforms 命名空间。
我该如何解决这个问题?
更新 3 (2011-06-15): 供应商终于回答了。简而言之,他们说Application.Run创建的消息泵和Thread.Join创建的消息泵有一些区别,但他们不知道那个区别是什么。
我同意他们的看法;任何关于此事的线索将不胜感激。
更新:
从 Richard 的评论到 mdm 的回答:
如果有其他组件是单线程的并从 MTA 实例化,那么 Windows 将创建工作线程 + 窗口 + 消息泵并进行必要的编组。
试图听从他的建议,我正在做以下事情:
更新 2:
我按照 João Angelo 的回答更改了代码。
using System;
namespace ConsoleApplication2
{
class Program
{
[STAThread]
static void Main(string[] args)
{
MyComObjectWrapper wrapper = new MyComObjectWrapper();
}
}
class MyComObjectWrapper
{
MyComObject m_Object;
AutoResetEvent m_Event;
public MyComObjectWrapper()
{
m_Event = new System.Threading.AutoResetEvent(false);
System.Threading.Thread t = new System.Threading.Thread(() => CreateObject());
t.SetApartmentState (System.Threading.ApartmentState.STA);
t.Start();
Wait();
}
void ObjectEvt(/*...*/)
{
// ...
}
void Wait()
{
m_Event.WaitOne();
}
void CreateObject()
{
m_Object = new MyComObject();
m_Object.OnEvent += ObjectEvt;
System.Threading.Thread.CurrentThread.Join();
}
}
}
我也尝试了以下方法:
public MyComObjectWrapper()
{
CreateObject();
}
【问题讨论】:
-
第三方组件的线程模型是什么?接收事件的 COM 代码的线程模型是什么?你在哪个 COM 公寓里跑?
-
@Richard:我在 STA 中运行。如何检查第 3 方组件的型号?和我的 COM 代码?什么COM代码?
-
第 3 方组件的线程模型将在注册表中。 “你是 COM 代码”:你传递给第 3 方组件的接口的实现,以便它用事件回调。
-
@Richard:我不确定。我在 HKCR/CLSID/{UUID}/InProcServer32 下找到了对具有不同 UUID 的对象的引用。其中一些具有 ThreadModel = "Neutral",一些具有 ThreadModel = "both"。关于我的COM代码,我仍然不知道你在说什么。我只是在我的类中实例化对象并添加一个事件处理程序,就像在 Daniel Hilgarth 代码中一样......