对循环内数据库的异步调用

问题描述 投票:2回答:2

我试图调用数据库并将结果存储在记录中,存储的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;
c# asynchronous task-parallel-library
2个回答
1
投票

这听起来像是并发错误; 无意并发访问连接;您允许重叠的读取器(如果启用了MARS),但是就尝试同时的多个线程而言,实际访问仍然不能并发。执行此操作时,所有行为都是不确定的。坦白说,我只是顺序执行这些命令,而不是同时执行。如果使用完全不相关的连接,请are可以同时工作,请注意。


0
投票

我之前修复了完全相同的错误。

列表不是线程安全的。

同时添加项时,列表的内部指针可能会混乱,即使添加了非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();
© www.soinside.com 2019 - 2024. All rights reserved.