2012-03-09 6 views
5

Ho un server COM nativo (Delphi) pubblicizzato come STA (Apartment Threaded Model).C'è qualche ragione per cui l'impostazione di un client .NET gestito per l'uso di thread STA potrebbe causare problemi con le eccezioni in un server COM nativo?

Contiene alcuni algoritmi che generano eccezioni di overflow in alcuni casi. Queste eccezioni sono gestite nel codice e tutto funziona come dovrebbe se accedo al server COM da un client sul thread principale.

Se il client è nativo (Delphi), posso accedere al server da più thread purché rispetti la regola che un oggetto creato su un thread rende tutte le sue chiamate di metodo dallo stesso thread.

Tuttavia, se il client è un client gestito (Vb.NET e C# testato), se si imposta l'ApartmentState dei thread client su MTA, tutto funziona correttamente, ma ottengo un risultato in termini di prestazioni.

Questo mi aspetto che, come suppongo, COM debba fare qualche pasticcio tremendo (ad esempio il marshalling) per assicurarsi che tutti siano felici.

Tuttavia, se cambio ApartmentState in STA e quindi assicuri una connessione diretta tra client e server, il client si bloccherà con un errore di errore, di solito un System.stackoverflowexception in CustomMarshallers.dll.

Se elimini i numeri che causano questi overflow, non ho problemi.

Posso aggirare questo modificando gli algoritmi per non dipendere da eccezioni (probabilmente come avrebbero dovuto essere scritti in primo luogo), ma vorrei capire le ragioni dietro ciò che sta accadendo.

+0

Il codice deve essere thread-safe in STA. –

+0

Il codice è thread-safe. Tutti i dati di istanza sono sicuri in quanto è garantito che vengano chiamati da un singolo thread. Tutti i dati globali sono stati protetti. – Steve

+0

Non banale, ma l'esecuzione del server COM in debugger può aiutare –

risposta

0

C'è una certa quantità di congetture coinvolte in questa risposta dato che non si cita testualmente il messaggio di errore e non si menzionano valori HRESULT.

Esiste una possibilità teorica che il diverso spazio di stack disponibile tra i casi STA e MTA possa fare la differenza per uno stack di un'applicazione Delphi. Ma la seguente possibilità è più probabile.

Il StackOverflowException è probabilmente causato dal lato stesso di Delphi (supponendo che il messaggio di errore lo definisca "non gestito"). Guarda più da vicino tutti i meccanismi di gestione degli errori sul lato Delphi e osserva tutti i meccanismi che potrebbero portare alla ricorsione in modo specifico sugli errori. Ad esempio, il codice in esecuzione su un particolare evento potrebbe contenere un blocco protetto in cui la clausola catch fa qualcosa che attiva lo stesso evento.

suppongo che la differenza che si vede con STA rispetto MTA sarebbe un po 'livellare se si rimuove il PreserveSigAttribute dal codice cliente, in modo che l'eccezione di overflow dello stack si fermerà di essere tradotto in un HRESULT che il vostro client ignora presumibilmente in questo momento . (Se è stato utilizzato tlbimp.exe, questo attributo è stato specificato in modo implicito. Significa che si desidera gestire le eccezioni in modo COM come valori di ritorno, non in .NET come eccezioni.)

+0

Tutti i punti validi senza dubbio, ma perché il client nativo lo gestisce senza problemi. Ho una linea specifica in uno dei miei algoritmi: – Steve

+0

: se [icol, icol] = 0, allora aumenta EMatrixError.Create ('Matrix Error'); Sto cercando di gestire questo errore, ma man mano che l'eccezione si risolve, ottengo l'errore. Quindi sì, l'errore nel codice Delphi, ma qualcosa nel.Il client NET sembra causare il problema – Steve

+0

@Steve - re "crash del client con errore di errore", puoi copiare e incollare il messaggio o lo stacktrace che vedi? Hai provato a stampare HRESULT dal client Delphi (non gestito), che il client probabilmente ignora in questo momento? Se la mia risposta è corretta, HRESULT sarà un codice di errore e "PreserveSigAttribute" sarà l'unica differenza tra i due client. –