Newsgroup: it.comp.lang.visual-basic
Titolo: [.NET] Reflection, Multi-threading, Dll compilate a runtime ed "Exception has been thrown by the target of an invocation."

Salve a tutti,
scrivo per cercare una soluzione ad un problema che si sta verificando presso un cliente.
Mi scuso in anticipo per la lunghezza del post ma vorrei essere il più chiaro possibile.
 
Premessa:
Abbiamo creato una dll in .NET (DTUEngine.dll) che prende del codice 
VB.NET
 o C# insieme ad una serie di altri parametri (comprese stringhe SQL ecc...) e compila tutto in una dll che chiamiamo [NomeRegola].dll dove [NomeRegola] cambia di volta in volta.
 
Questo per dare all'utente un IDE in cui scrivere una serie di regole ETL simili, per darvi un idea, ai DTS\SSIS di SQL Server.
Questa DTUEngine, sostanzialmente, esegue una query SQL "sorgente" e, con un DataReader, popola un dictionary che è chiamato DTSSource , che a qualcuno può ricordare qualcosa ;-)
DTUEngine si occupa anche di inizializzare 2 ulteriori Dictionary: DTSDestination e DTSGlobalVariables.
 
Una volta che tutti e tre i dizionari sono popolati, li passa ByRef alla funzione ExecDT di [NomeRegola].dll, la quale esegue una serie di operazioni e restituisce un flag che indica lo stato dell'elaborazione.
 
Tutto ciò viene eseguito per ogni record estratto.
 
DTUEngine può lavorare in *single-thread* o in *multi-thread*.
 
Problema:
Finora abbiamo utilizzato questa dll su svariati clienti, anche in multi-threading, senza mai avere problemi... stiamo parlando di oltre 4 anni di funzionamento senza errori.
Oggi sull'ambiente di un cliente che fa pesante uso di multi-threading, per via della mole di dati da elaborare, ci viene spesso restituito questo errore:
 
JobDTU  MainDTU  ExecDT (Run): Exception has been thrown by the target of an invocation.
 
    at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
    at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
    at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
    at DTUEngine.clsDTU.ExecDT(Dictionary`2& DTSDestination, Dictionary`2& DTSSource, Dictionary`2& DTSGlobalVariables) in C:\\SorgentiSDI\\Eagle3.5\\Eagle3.5.0\\Moduli Esterni\\DTU\\DTUEngine\\DTUEngine\\clsDTU.vb:line 894
 
La riga 894 in clsDTU.vb è la Invoke:
 
Opresult = Atype.InvokeMember("ExecDT", BindingFlags.Default Or BindingFlags.InvokeMethod Or BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public, Nothing, Istanza, sArgs)
 
Sono moderatamente sicuro che DTUEngine in sè non c'entra, come anche il fatto che tutte le variabili utilizzate in DTUEngine sono studiate per essere thread-safe. L'errore si scatena su quella riga solo perchè è il punto in cui viene restituito l'errore.
 
L'errore si presenta "a random" e quando eseguo più regole in contemporanea (a loro volta con più thread interni).
Qualcuno di voi saprebbe dirmi se la cosa può essere legata la cosa? Qualche errore nelle regole [NomeRegola].dll per cui qualche variabile potrebbe non essere thread-safe? O magari il numero di thread che .NET 2.0 non riesce a gestire (nella situazione di maggior carico possono girare 8 regole diverse in parallelo, ognuna da 10 thread contemporanei).
 
Grazie e scusate se sono stato prolisso.
 
Nicola

 viene restituito l'errore.
la prima cosa da fare ï¿œ scoprire quale sia l'eccezione vera, quindi 
devi riuscire a fare il dump di tutte l'eccezione e di tutte le inner 
exception perchï¿œ TargetInvocationException ï¿œ solo un "wrapper" per il 
marshaling delle eccezioni da thread diversi verso il main thread.
.m
-- 
ï¿œ corta

Ciao Mauro,
scusa se ti rispondo in ritardo ma solo oggi sono riuscito a metterci la testa sul problema.
Effettivamente avevi ragione, cercavo di intercettare l'InnerException ma nel posto sbagliato.
Aggiunta la gestione dell'InnerException anche in un altro punto sono riuscito a capire che l'errore era di timeout dovuto al troppo carico di lavoro sul server SQL.
 
Grazie mille,
 
Nicola