Вставить 100000 записей в MySQL с задачами - C#
У меня проблемы с моим кодом. Я пытаюсь вставить около 100 000 элементов в таблицу Mysql, используя Задачи, чтобы ускорить процесс. Вот мой код:
List < Task > tasks = new List < Task > ();
int counter = 0;
foreach(var folder in dirs) {
object lockTarget = new object();
tasks.Add(Task.Factory.StartNew(() => {
try {
comm.CommandText = "INSERT INTO webdata(url,title) VALUES(?sUrl,?sTitle,) ON DUPLICATE KEY UPDATE url=?sUrl,title=?sTitle";
comm.Parameters.Add("?sUrl", MySql.Data.MySqlClient.MySqlDbType.VarChar).Value = url;
comm.Parameters.Add("?sTitle", MySql.Data.MySqlClient.MySqlDbType.VarChar).Value = title;
var mysql_return = comm.ExecuteNonQueryAsync();
lock(lockTarget) {
counter++;
Console.WriteLine("\rProcessing {0} of {1} - {2} {3}", counter, dirs.Length, folder, mysql_return.Status);
}
} catch (MySql.Data.MySqlClient.MySqlException ex) {
Console.WriteLine(ex.Message);
}
}));
}
Task.Factory.StartNew(() => {
Task.WaitAll(tasks.ToArray());
Console.WriteLine("Finished");
conn.Close();
});
Итак, когда я запускаю свой код, некоторые из задач (mysql_return) возвращаются rantocompletion
и немного Faulted
Таким образом, только половина моих записей фактически вставлена в БД.
Я мог бы использовать ExecuteNonQuery
и нет Task
но потребуется много времени, чтобы вставить так много данных. Это проблема из-за аппаратного обеспечения (процессор не справляется с тысячами порожденных задач) или из-за моего кода?
Есть идеи? заранее спасибо
1 ответ
Проблема1: comm
модифицируется в нескольких потоках, кажется, это должна быть локальная переменная.
Проблема 2: Вы не ждете задачи, возвращенной ExecuteNonQueryAsync
и поэтому Task
вернулся StartNew
не буду ждать завершения ExecuteNonQueryAsync
быть законченным.
В конце концов вы закрываете соединение, предполагая, что все сделано, но это не так. Все они запущены, но не завершены.
Вам нужно использовать дождаться результата ExecuteNonQueryAsync
(для этого использования async
лямбда) а также звоните Task.UnWrap
или использовать Task.Run
что дает вам UnWrap
бесплатно.
Таким образом, ваш код станет примерно таким:
tasks.Add(Task.Run(async () => //Note Task.Run and async lambda
{
try
{
var comm = new WhateverCommand();
...
var mysql_return = await comm.ExecuteNonQueryAsync();//Note the await
...
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
Console.WriteLine(ex.Message);
}
}));