NullReferenceException,而涉及的对象有效

时间:2013-01-02 05:06:16

标签: c# multithreading datatable nullreferenceexception

NullReferenceException被抛出到所有相关对象都有效的行上。 StackTrace显示第#行是432。

代码是

enter image description here

此处,FlagstempFlags都是数据表。两个数据表的列的数据类型都是原始的(十进制,日期时间,短)。该应用程序是一个多线程应用程序,代码片段属于线程函数。 Flags在实例级别被decalred,即在线程函数内声明tempFlags时共享给所有线程。

在这个特定的时间实例中,Flags包含1946条记录而tempFlags包含1.那么,为什么这个NullReferenceException ??

编辑#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"

编辑#2

看起来Merge语句不是线程安全的,因为在将432行放入锁之后,异常就消失了,所以很快。

3 个答案:

答案 0 :(得分:3)

每当你从框架中获得NullReferenceException并且你是多线程时,几乎可以肯定是一个线程安全问题,你不应该在你应该的地方应用锁。

答案 1 :(得分:2)

由于在插入新行时似乎正在发生System.Data.DataTable.InsertRow(DataRow row, Int64 proposedID),我猜有一个约束,说字段不能为空。而您正试图从源表中插入一个空值。

或者,有一个计算列,其中一个输入列为空。

答案 2 :(得分:1)

特定于此段代码的此异常(IMO)的说明。

让我们说线程A正在执行Merge并传递存储在Merge中的数据Dt1 referenceToDatatable,同时

线程B进来并将Dt2传递给MergeMerge存储在referenceToDatatableDt1(引用相同,因为非原始对象通过引用传递,合并不是线程安全的,并且没有锁定)因此Dt2会覆盖Dt2

到目前为止没有例外,因为null结构相同且不是Merge

现在线程B被暂停并且线程A进入,完成Dt1并退出,因此使referenceToDatatable无效,这也使referenceToDatatable = null无效。

现在线程B进来找到{{1}} - >的异常