2014-12-11 1 views
1

У меня возникли проблемы с моим кодом. Я пытаюсь вставить около 100 000 элементов в таблицу Mysql, используя Tasks для ускорения процесса. Вот мой код:Ввести 100 000 записей в MySQL с задачами - C#

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, таким образом, только 1/2 из моих записей на самом деле вставляется в БД.

Я мог бы использовать ExecuteNonQuery и не Task, но потребуется столько времени, чтобы вставить столько данных. Является ли проблема из-за аппаратного обеспечения (CPU не может справиться с тысячами нерешенных задач) или из-за моего кода?

Любые идеи? Заранее спасибо

+2

Почему нельзя просто вставить вместо партии? http://stackoverflow.com/questions/5526917/how-to-do-a-batch-insert-in-mysql – sed

ответ

4

задачи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); 
     }  
})); 
+0

@ Theodoros80 Но помните, только если вы решите обе проблемы, которые вы можете достичь успеха. –

+1

Спасибо, я попробую. Теперь некоторые вещи ясны. – Theodoros80