为什么在STA线程下运行时不会引发此COM互操作事件?

时间:2009-06-19 13:30:40

标签: multithreading events sta

有人可以解释为什么在下面的代码中使用STA线程时不会引发事件“OnNewMail”吗?该程序试图使用Redemption库来拦截传入的Outlook邮件。

class Program
{        
    [STAThread()] // When this line is deleted the application works
    static void Main(string[] args)
    {
        RDOSession session = GetSession();
        session.OnNewMail += Session_OnNewMail;
        Console.ReadLine();
    }

    static void Session_OnNewMail(string EntryID)
    {
         Console.WriteLine("New mail received");
    }

    private static RDOSession GetSession()
    {
        var session = new RDOSession();
        var application = new ApplicationClass();

        session.MAPIOBJECT = application.Session.MAPIOBJECT;
        return session;
    }
}

3 个答案:

答案 0 :(得分:1)

在STAThread上运行的COM使用消息泵来引发事件和调用方法。在控制台应用程序中没有为您提供消息的窗口,因此您需要自己运行泵。 (一些.NET同步方法将为您完成此任务 - 查看WaitOne等...)

如果对象在默认MTA线程中感到满意 - 如果需要从控制台应用程序执行此操作,最好使用它。

而不是ReadLine - 您可以使用以下方法轮询密钥并输出消息:

while (Console.Read() == 0)
{
    Thread.CurrentThread.Join(100);
}

......但这是一个黑客攻击。

混合COM,控制台应用程序和[STAThread]有点可疑,可能会导致其他问题: http://support.microsoft.com/default.aspx/kb/828988

答案 1 :(得分:0)

当胎面是STA线程并且您等待输入时,图书馆无法同时执行任何操作,并且在电子邮件到达时无法触发事件。

答案 2 :(得分:0)

问题几乎肯定与消息泵送有关。

除非我们知道什么类型的COM对象RDOSession(STA,MTA等...),否则我们只能猜测实际发生了什么。

我的猜测是RDOSession是一个MTA COM对象,并且事件代码以某种方式将事件绑定到STA代理或对象。这意味着OnNewMail事件的部分引发必须将引发编组到STA线程上。这涉及窗口消息传递。您正在执行一个简单的ReadLine调用,这是一个阻塞调用,不会处理消息。因此,你永远不会得到这个事件。