我试图调用数据库并将结果存储在记录中,存储的proc总是返回4条记录,但是有时我得到3条记录,而读取器显示4个计数,但第一条记录为空。代码有什么问题?
List record = new List();
List<Task> listOfTasks = new List<Task>();
for (int i = 0; i < 2; i++)
{
listOfTasks.Add(Task.Factory.StartNew(() => {
IDataCommand cmd = ds.CreateCommand("DropTicket", "returnTableTypeData",
CommandType.StoredProcedure);
IDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
TicketTextOutputRecord rec = new TicketTextOutputRecord();
rec.ValidationNumber = (string)reader["ValidationNumber"];
rec.IsSuccess = (bool)reader["IsSuccess"];
rec.Error = (string)reader["Error"];
record.Add(rec);
}
//reader.Close();
//reader.Dispose();
}));
}
Task.WaitAll(listOfTasks.ToArray());
return record;
这听起来像是并发错误; 无意并发访问连接;您是允许重叠的读取器(如果启用了MARS),但是就尝试同时的多个线程而言,实际访问仍然不能并发。执行此操作时,所有行为都是不确定的。坦白说,我只是顺序执行这些命令,而不是同时执行。如果使用完全不相关的连接,请are可以同时工作,请注意。
我之前修复了完全相同的错误。
列表不是线程安全的。
同时添加项时,列表的内部指针可能会混乱,即使添加了非null值,也可能导致项返回null。
这会产生问题:
var list = new List<object>();
var listOfTasks = new List<Task>();
for (var i = 0; i < 10; i++)
{
listOfTasks.Add(Task.Factory.StartNew(() => list.Add(new object())));
}
Task.WaitAll(listOfTasks.ToArray());
使用线程安全列表将解决此问题。但是,我将更改任务以返回结果,而不是将其添加到列表中。然后使用LINQ或Task.WhenAll
获得这些结果。
var listOfTasks = new List<Task<object>>();
for (var i = 0; i < 10; i++)
{
listOfTasks.Add(Task.Factory.StartNew(() => new object()));
}
var list = await Task.WhenAll(listOfTasks.ToArray());
// OR
Task.WaitAll(listOfTasks.ToArray());
var list = listOfTasks.Select(t => t.Result).ToList();