为什么在 STA 线程下运行时不会引发此 COM 互操作事件?
有人可以解释为什么在下面的代码中使用 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;
}
}
Can somebody please explain why the event "OnNewMail" is not raised when using an STA thread in the code below? The program attempts to use the Redemption library to intercept incoming outlook mails.
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;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 STAThread 上运行的 COM 使用消息泵来引发事件和调用方法。 在控制台应用程序中,没有窗口可以为您发送消息,因此您需要自己运行泵。 (一些 .NET 同步方法将为您执行此操作 - 看看 WaitOne 等...)
如果对象在默认 MTA 线程中运行正常 - 如果您需要从控制台应用程序。
您可以使用以下方法轮询密钥并泵送消息,而不是 ReadLine:
...但这是一个 hack。
混合 COM、控制台应用程序和 [STAThread] 有点可疑,可能会导致其他问题:
http://support.microsoft.com/default.aspx/kb/828988
COM running on an STAThread uses a message pump to raise events and call methods. When in a console application there isn't a window to pump messages for you so you need to run the pump yourself. (Several of the .NET synchronisation methods will do this for you - have a look at WaitOne etc...)
If the object is happy within a default MTA thread - you may be better off using that if you need to do this from a console application.
Instead of ReadLine - you can poll for a key and pump messages using this:
...but this is a hack.
Mixing COM, console apps and [STAThread] is a bit fishy and can result in other problems:
http://support.microsoft.com/default.aspx/kb/828988
当线程是 STA 线程并且您等待输入时,库无法同时执行任何操作,并且在电子邮件到达时没有机会触发事件。
When the tread is STA thread and you wait for input the library can't do anything at the same time and has no chance to fire the event when an email arrives.
这个问题几乎肯定与消息泵有关。
除非我们知道 COM 对象 RDOSession 是什么类型(STA、MTA 等),否则我们只能推测实际发生的情况。
我的猜测是 RDOSession 是一个 MTA COM 对象,并且事件代码以某种方式将事件绑定到 STA 代理或对象。 这意味着 OnNewMail 事件引发的一部分必须将引发封送到 STA 线程上。 这涉及到窗口消息传递。 您正在执行一个简单的 ReadLine 调用,这是一个阻塞调用,不会处理消息。 因此你永远不会得到这个事件。
The problem almost certainly has to do with message pumping.
Unless we know what type of COM object RDOSession is (STA, MTA, etc ...) we can only speculate as to what is actually going on.
My guess is that RDOSession is an MTA COM object and that somehow the event code has bound the event to an STA proxy or object. This means that part of the raising of the OnNewMail event must marshal the raise onto the STA thread. This involves window message passing. You are doing a simple ReadLine call which is a blocking call and will not process messages. Hence you won't ever get the event.