gpt4 book ai didi

c# - 如何处理来自控制台应用程序的 COM 事件?

转载 作者:可可西里 更新时间:2023-11-01 08:23:32 28 4
gpt4 key购买 nike

我正在使用来自第三方库的 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();
}

最佳答案

如果您使用的是 STA,那么您将需要一种或多种消息循环。如果您不需要消息循环,MTA 可能是最简单的方法,也是控制台样式应用程序的最佳选择。

需要注意的一件事是,对于 MTA,哪个线程创建了对象并不重要;一个 MTA 线程创建的所有对象同样属于所有 MTA 线程。 (或者,用 COM 的话说,一个进程只有一个多线程单元,所有 MTA 线程都在其中。)这意味着如果您采用 MTA 方法,则根本不需要创建单独的线程 -只需从主线程创建对象。但您还需要注意传入事件将在“随机”线程上传递,因此您必须采取单独的步骤与主线程通信。

using System;
using System.Threading;

class Program
{
static MyComObject m_Object;
static AutoResetEvent m_Event;


[MTAThread]
static void Main(string[] args)
{
m_Event = new AutoResetEvent(false);

m_Object = new MyComObject();
m_Object.OnEvent += ObjectEvt;

Console.WriteLine("Main thread waiting...");
m_Event.WaitOne();
Console.WriteLine("Main thread got event, exiting.");
// This exits after just one event; add loop or other logic to exit properly when appropriate.
}

void ObjectEvt(/*...*/)
{
Console.WriteLine("Received event, doing work...");

// ... note that this could be on any random COM thread.

Console.WriteLine("Done work, signalling event to notify main thread...");
m_Event.Set();
}
}

对您以前版本的代码的一些评论:您在 CreateObject 和 MycomObjectWrapper 构造函数中调用了 Wait();似乎你应该只有一个 - 如果你有两个,当调用 m_Event.Set() 时只有一个会被释放,另一个仍然在等待。此外,建议添加一些调试代码,以便您了解自己的进展情况。这样您至少可以判断您是否从 COM 获取事件,以及您是否成功地将事件传回主线程。如果对象在注册表中标记为中性或两者都标记为中性,则从 MTA 创建它们应该没有问题。

关于c# - 如何处理来自控制台应用程序的 COM 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6185610/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com