2012-10-19 22 views
9

Sto tentando di registrare in modo asincrono alcune informazioni su SQL Server all'interno di un'azione del controller MVC 4 con targeting per .NET 4.0 utilizzando AsyncTargetingPack. Vorrei passare direttamente a .NET 4.5, ma la mia app vive in Azure e we're still waiting for the update ...Registrazione asincrona che lancia una eccezione NullReferenceException

Questo codice funziona come previsto (una riga viene scritta al mio database senza eccezioni generate):

public class SystemActionLogger : ISystemActionLogger 
{ 
    private readonly ActionBlock<Tuple<SystemAction, object>> actionBlock; 

    public SystemActionLogger(ISystemActionLogEntryRepository repository) 
    { 
     actionBlock = new ActionBlock<Tuple<SystemAction, object>>(
      entry => TaskEx.Run(async() => 
       { 
        string data = await JsonConvert.SerializeObjectAsync(entry.Item2); 
        await repository.PersistAsync(new SystemActionLogEntry(entry.Item1, data)); 
       })); 
    } 

    public void Log(SystemAction systemAction, object data) 
    { 
     actionBlock.Post(new Tuple<SystemAction, object>(systemAction, data)); 
    } 
} 

E questo codice genera un NullReferenceException:

public class SystemActionLogger : ISystemActionLogger 
{ 
    private readonly ActionBlock<Tuple<SystemAction, object>> actionBlock; 

    public SystemActionLogger(ISystemActionLogEntryRepository repository) 
    { 
     actionBlock = new ActionBlock<Tuple<SystemAction, object>>(async entry => 
      { 
       string data = await JsonConvert.SerializeObjectAsync(entry.Item2); 
       await repository.PersistAsync(new SystemActionLogEntry(entry.Item1, data)); 
      }); 
    } 

    public void Log(SystemAction systemAction, object data) 
    { 
     actionBlock.Post(new Tuple<SystemAction, object>(systemAction, data)); 
    } 
} 

NullReferenceException: "oggetto non impostato a un'istanza di un oggetto."

Server stack trace: 
    at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext) 
    at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext) 
    at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state) 
    at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state) 
    at System.Runtime.CompilerServices.TaskAwaiter.<>c__DisplayClassa.<OnCompletedInternal>b__0(Task param0) 

Exception rethrown at [0]: 
    at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(Object state) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 
    at System.Threading.ThreadPoolWorkQueue.Dispatch() 

Non ho visibilità nell'eccezione poiché è tutto il codice esterno. Non capisco perché il secondo blocco di codice fallisce. Questo è il codice che ho originariamente scritto.

Cosa sto sbagliando?

+0

ASP.NET ha bisogno di supporto speciale per 'async', che è stato aggiunto in .NET 4.5. Non proverei a utilizzare Async Targeting Pack su app ASP.NET per .NET 4.0: alcune semplici cose funzionerebbero ma la pipeline ASP.NET non è pronta per vedere il codice 'async'. –

+1

La traccia dello stack include un riferimento a "LegacyAspNetSynchronizationContext", un tipo aggiunto in .NET 4.5. Hai installato .NET 4.5 sul tuo server Azure? –

+0

Ehi Stephen, grazie per la risposta. Avevo visto una risposta simile da te su un altro post SO e speravo che non fosse così, specialmente dal momento che il primo blocco di codice funziona. Per quanto riguarda il tipo, ho installato .NET 4.5 sulla mia scatola ma non ho tentato di saltare attraverso i loop e di renderlo una parte del mio pacchetto di distribuzione in Azure. Questa è un'osservazione interessante. –

risposta

0

Dataflow funziona solo su .NET 4.5. Il fatto che tu stia eseguendo su .NET 4.0 non è supportato ed è probabile che tu stia vedendo eccezioni spurie.

5

Avevo solo un problema molto simile (NullReference da AssociateWithCurrentThread quando si utilizza un'attività di registrazione).

Il problema che stavo avendo era che l'azione originale non ha atteso il completamento del compito di registrazione, in modo che quando le finiture di registro e cerca di rientrare nel thread originale un nullReference è gettato in quanto il thread originale è terminato.

Ciò è stato risolto per me assicurandomi che il controllore della richiesta fosse in attesa della funzione di registrazione.

-2

Ho avuto questo problema con .net4.5 quando il mio servizio web stava invocando un altro servizio WCF in modo asincrono. Ho semplicemente aggiunto un breve periodo Wait() perché non mi importava della risposta (evento di telemetria).

public static void Event(string key, string message) { 
    Telemetry.Event(key, message).Wait(100); 
} 
Problemi correlati