Asyn c вызов базы данных внутри цикла - PullRequest
2 голосов
/ 01 апреля 2020

Я пытаюсь позвонить в базу данных и сохранить результат в записи, сохраненный pro c всегда возвращает 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;

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

Это звучит как ошибка параллелизма; не предназначено для одновременного доступа к соединению; вам разрешено разрешать перекрывающиеся считыватели (если включен MARS), но фактический доступ все равно не должен быть параллельным с точки зрения нескольких потоков, пытающихся сделать что-то в одно и то же время . В тот момент, когда вы это делаете, все поведение не определено. Честно говоря, я бы выполнял их последовательно, а не одновременно. Вам разрешено работать одновременно, если вы используете совершенно не связанные соединения, обратите внимание.

0 голосов
/ 01 апреля 2020

Я исправил точно такую ​​же ошибку раньше.

Список не является потокобезопасным.

При одновременном добавлении элементов внутренний указатель списка может запутаться и привести к тому, что элемент вернет ноль, даже если было добавлено ненулевое значение.

Это приводит к возникновению проблемы:

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...