2013-01-02 24 views
6

NullReferenceException viene lanciato su una riga in cui tutti gli oggetti coinvolti sono validi. StackTrace mostra la linea # è 432.NullReferenceException mentre gli oggetti coinvolti sono validi

Il codice è

enter image description here

Qui, Flags e tempFlags entrambi sono DataTable. I tipi di dati di colonne di entrambi i datatables sono primitivi (decimal, datetime, short). L'applicazione è un'applicazione multithread e lo snippet di codice appartiene alla funzione thread. Flags viene decodificato a livello di istanza, cioè condiviso con tutti i thread mentre tempFlags viene dichiarato all'interno della funzione thread.

Qui in questo particolare istante di tempo lo Flags contiene record 1946 e tempFlags contiene 1. Quindi, perché questa NullReferenceException ??

Modifica # 1

ex.InnerException 
null 
ex.StackTrace 
at System.Data.DataTable.RecordStateChanged(Int32 record1, DataViewRowState oldState1, DataViewRowState newState1, Int32 record2, DataViewRowState oldState2, DataViewRowState newState2) 
at System.Data.DataTable.InsertRow(DataRow row, Int64 proposedID) 
at System.Data.DataTable.MergeRow(DataRow row, DataRow targetRow, Boolean preserveChanges, Index idxSearch) 
at System.Data.Merger.MergeTable(DataTable src, DataTable dst) 
at System.Data.Merger.MergeTableData(DataTable src) 
at System.Data.Merger.MergeTable(DataTable src) 
at System.Data.DataTable.Merge(DataTable table, Boolean preserveChanges, MissingSchemaAction missingSchemaAction) 
at System.Data.DataTable.Merge(DataTable table) 
at [...].cs:line 432" 
ex.Data 
    {System.Collections.ListDictionaryInternal} 
     [System.Collections.ListDictionaryInternal]: {System.Collections.ListDictionaryInternal} 
     IsFixedSize: false 
     IsReadOnly: false 
     Keys: {System.Collections.ListDictionaryInternal.NodeKeyValueCollection} 
     Values: {System.Collections.ListDictionaryInternal.NodeKeyValueCollection} 
ex.Message 
"Object reference not set to an instance of an object." 
ex.Source 
"System.Data" 

Modifica # 2

Sembra la dichiarazione di unione non è thread-safe come dopo aver messo la linea 432 all'interno di un blocco, l'eccezione è andato, FINORA .

+0

Usi serratura per tempFlags? mentre stai cancellando tempFlags. – Adil

+1

Puoi pubblicare i dettagli delle eccezioni? Eccezione interna, traccia dello stack, ecc. – ryadavilli

+0

@Adil Non dovrebbe importare, giusto? L'eccezione viene lanciata prima di quella riga e 'tempFlags' è una variabile locale nel metodo. –

risposta

1

Spiegazione di questa eccezione (IMO) specifica per questo pezzo di codice.

ci permette di dire thread A sta eseguendo Unire e passa DataTable Dt1 che è memorizzato in Merge come referenceToDatatable, nel frattempo

Discussione B entra e passa Dt2-Merge che è memorizzato in Merge come referenceToDatatable (il riferimento è lo stesso perché gli oggetti non primitivi vengono passati per referenza, Merge non è thread-safe e non c'è alcun Lock) e quindi lo Dt1 viene sovrascritto da Dt2.

Nessuna eccezione finora perché Dt2 è della stessa struttura e non è null.

Ora il thread B è sospeso e il thread A entra, completa Merge ed esce, quindi annulla Dt1 che annulla anche referenceToDatatable.

Ora filo B entra e trova referenceToDatatable = null ->Eccezione

2

Poiché sembra che stia succedendo quando si inserisce una nuova riga, System.Data.DataTable.InsertRow(DataRow row, Int64 proposedID) Direi che c'è un vincolo che dice che un campo non può essere nullo. E stai provando ad inserire un null dalla tabella di origine.

Oppure, c'è una colonna calcolata e una delle colonne di input è null.

+0

Questa [risposta] (http://stackoverflow.com/a/490569/649524) suggerisce misure preventive per questo problema. – Tilak

2

Ogni volta che si ottiene NullReferenceException dall'interno del framework e si sta eseguendo il multithreading, è quasi certamente un problema di sicurezza del thread in cui non si applicano i blocchi dove si dovrebbe essere.

+0

Mi rallenta solo perché la funzione long life del framework non è sicura per i thread !!! – bjan

+1

@bjan A meno che gli oggetti dichiarino di essere thread-safe nella documentazione, non possono essere utilizzati in modo sicuro come tali senza le serrature/barriere/precauzioni corrette. * Questo non è diverso dal 99 +% del codice che io (o tu) scrivi che non è thread-safe perché non è stato meticolosamente progettato per essere. * Non incolpare il codice che viene utilizzato al di fuori dei suoi limiti contrattuali. (Vorrei solo permettere ad un thread di accedere al DT in qualsiasi momento tramite un semplice lock - o meglio, lasciare che un thread "possieda" un DT in un dato momento - e vedere se ciò "risolve" i problemi osservati. "Più veloce".) –

Problemi correlati