このCOM相互運用イベントがSTAスレッドの下で実行中に発生しないのはなぜですか?
-
06-07-2019 - |
質問
イベント" OnNewMail"の理由を誰か説明してください。以下のコードでSTAスレッドを使用すると発生しませんか?プログラムは、受信ライブラリを使用して受信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;
}
}
解決
COMは、メッセージポンプを使用してイベントを発生させ、メソッドを呼び出します。コンソールアプリケーションでは、メッセージを送信するためのウィンドウがないため、自分でポンプを実行する必要があります。 (いくつかの.NET同期メソッドがこれを行います-WaitOneなどをご覧ください...)
デフォルトのMTAスレッド内でオブジェクトが満足している場合-コンソールアプリケーションからこれを行う必要がある場合は、それを使用した方がよい場合があります。
ReadLineの代わりに、これを使用してキーをポーリングし、メッセージを送信できます。
while (Console.Read() == 0)
{
Thread.CurrentThread.Join(100);
}
...しかしこれはハックです。
COM、コンソールアプリ、[STAThread]の混合は少々厄介で、他の問題を引き起こす可能性があります。 http://support.microsoft.com/default.aspx/kb/828988
他のヒント
トレッドがSTAスレッドであり、入力を待機している場合、ライブラリは同時に何も実行できず、メールが到着したときにイベントを起動する機会がありません。
この問題は、ほぼ確実にメッセージポンピングに関係しています。
COMオブジェクトRDOSessionのタイプ(STA、MTAなど)がわからない限り、実際に何が起こっているのかを推測することしかできません。
RDOSessionはMTA COMオブジェクトであり、イベントコードが何らかの形でイベントをSTAプロキシまたはオブジェクトにバインドしていると思います。これは、OnNewMailイベントの発生の一部が、発生をSTAスレッドにマーシャリングする必要があることを意味します。これには、ウィンドウメッセージの受け渡しが含まれます。ブロッキング呼び出しであり、メッセージを処理しない単純なReadLine呼び出しを行っています。したがって、イベントを取得することはありません。