I found this in an error log and am trying to work out how it s possible. It s not every day that a NullReferenceException turns up deep within the .net base classes!
1) Exception Information
*********************************************
Exception Type: System.NullReferenceException
Message: Object reference not set to an instance of an object.
Data: System.Collections.ListDictionaryInternal
TargetSite: Void Bind(System.Data.SqlClient.TdsParserStateObject)
HelpLink: NULL
Source: System.Data
StackTrace Information
*********************************************
at System.Data.SqlClient.SqlDataReader.Bind(TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult esult)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet)
at MyCode.Shared.Data.DataSocket.GetTable(String SPString)
at <rest of stack trace>
我所能想到的唯一可能是,在同一时间有两个线程执行了同一个方法,其中一个清除或修改了传递给Fill()的DataSet。所以我的问题真正是:
- how could this exception get thrown
- Could a multi-thread scenario cause this exception
- How can I be sure, eg is there a way i can step through the System.Data methods to replicate the problem?
顺便提一句,我发现了另外几个此问题的案例,一个在此线程中,另一个在某人页面的谷歌高速缓存中。但是,两者似乎都没有什么帮助。
The GetTable() method of mine that is being executed looks like this:
public DataTable GetTable(string SPString)
{
//Setup the data objects by calling helper
prepareDataAdaptor(SPString,CommandType.Text);
dataAdaptor.Fill(dataSet);
dataAdaptor.SelectCommand.Connection.Close();
DataTable dt;
//ensure we dispose okay
using(dataSet)
{
if(dataSet.Tables.Count==0)
{
dataSet.Tables.Add(new DataTable("EmptyTable"));
}
dt=dataSet.Tables[0];
//because we are disposing we need to remove the table from the dataset
dataSet.Tables.Clear();
}
return dt;
}
private void prepareDataAdaptor(string SPString,CommandType Type)
{
checkForConnection();
dataSet=new DataSet();
dbCommand.CommandText=SPString;
dbCommand.CommandTimeout = MySettings.CommandTimeout;
dataAdaptor.SelectCommand=dbCommand;
dataAdaptor.SelectCommand.CommandType=Type;
dataAdaptor.SelectCommand.Connection=dbConnection;
dataAdaptor.SelectCommand.Parameters.Clear();
}
dataAdaptor (sic) is an instance variable declared as an IDbDataAdapter populated with a SqlDataAdapter. dataSet is an instance variable of type DataSet.
My theory goes that thread A runs through and gets partway into the SqlDataAdapter.Fill() method. Meanwhile thread B is also executing and does something that messes up thread A, like this line:
dataAdaptor.SelectCommand.Connection.Close();
我可以看出我的这个代码不是线程安全的,但我怎么确定这是导致上述异常的问题?
many thanks for any suggestions!
罗里 (Luó lǐ)
更正:拼写很差,请忽略。我没有更新代码,因为它就是这样的。
更新:我同意这个代码存在几个需要修复的问题,但我的主要兴趣在于是否有任何方法可以验证是线程问题导致了此错误。考虑到我的应用程序,这有点牵强,但这是我所能想到的唯一事情。在我修改代码以使其更好之前,我想确定异常的原因,以便我可以确定已经修复了它。
有没有办法进入.NET代码?例如,我使用的是VS 2005 / .net 2.0,但我认为在VS 2008中,您可以查看.NET框架源代码?如果是这种情况,我是否可以创建一个2线程的场景,并通过步进来重新创建此问题?或者是否有一种不需要我安装VS 2008的方法?