1

我的代码有一些问题。我正在尝试使用 Tasks 在 Mysql 表中插入大约 100.000 个项目以加快进程。这是我的代码:

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 无法跟上数千个衍生任务)还是由于我的代码?

有任何想法吗?提前致谢

4

1 回答 1

4

问题1comm似乎在多个线程中进行了修改,这必须是一个局部变量。

问题2:您没有等待返回的任务ExecuteNonQueryAsync,因此Task返回的任务StartNew不会等待ExecuteNonQueryAsync完成。

最终,您关闭连接,假设一切都已完成,但尚未完成。它们都开始了,但还没有完成。

您需要使用 await the result of ExecuteNonQueryAsync(for that use asynclambda) 并免费调用Task.UnWrap或使用Task.RunUnWrap

所以你的代码将变成如下所示:

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);
      }    
}));
于 2014-12-11T15:03:54.903 回答