Perché questo evento di interoperabilità COM non viene generato durante l'esecuzione in un thread STA?

StackOverflow https://stackoverflow.com/questions/1017968

  •  06-07-2019
  •  | 
  •  

Domanda

Qualcuno può spiegare perché l'evento " OnNewMail " non viene generato quando si utilizza un thread STA nel codice seguente? Il programma tenta di utilizzare la libreria Redemption per intercettare i messaggi di Outlook in arrivo.

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;
    }
}
È stato utile?

Soluzione

COM in esecuzione su STAThread utilizza un pump di messaggi per generare eventi e chiamare metodi. Quando in un'applicazione console non è presente una finestra per il pompaggio dei messaggi, è necessario eseguire il pump da soli. (Molti dei metodi di sincronizzazione .NET lo faranno per te - dai un'occhiata a WaitOne ecc ...)

Se l'oggetto è soddisfatto all'interno di un thread MTA predefinito, è possibile utilizzarlo meglio se è necessario farlo da un'applicazione console.

Invece di ReadLine - puoi eseguire il polling di una chiave e pompare i messaggi usando questo:

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

... ma questo è un trucco.

Il mixaggio di COM, app della console e [STAThread] è un po 'complicato e può causare altri problemi: http://support.microsoft.com/default.aspx/kb/828988

Altri suggerimenti

Quando il battistrada è thread STA e si attende l'input, la libreria non può fare nulla allo stesso tempo e non ha alcuna possibilità di attivare l'evento quando arriva un'e-mail.

Il problema ha quasi certamente a che fare con il pumping dei messaggi.

Se non sappiamo che tipo di oggetto COM è RDOSession (STA, MTA, ecc ...) possiamo solo speculare su ciò che sta realmente accadendo.

La mia ipotesi è che RDOSession sia un oggetto COM MTA e che in qualche modo il codice dell'evento abbia associato l'evento a un proxy o oggetto STA. Ciò significa che una parte del rilancio dell'evento OnNewMail deve eseguire il marshalling del rilancio sul thread STA. Ciò comporta il passaggio di messaggi dalla finestra. Stai effettuando una semplice chiamata ReadLine che è una chiamata bloccante e non elaborerà i messaggi. Quindi non riceverai mai l'evento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top