多线程错误:此连接已关联一个必须先关闭的打开的DataReader。

6

我有一个Parallel.Foreach循环

var options = new ParallelOptions();
options.MaxDegreeOfParallelism = 1;
Parallel.ForEach(urlTable.AsEnumerable(),drow =>
{
    using (var WCC = new MasterCrawlerClass())
    {
        WCC.MasterCrawlBegin(drow);
    }
 }

这个循环调用了类并遍历了所有的数据行,但是每一个数据行都会进行DataTable的填充或者对MySQL数据库执行更新命令。下面是我为这两种情况编写的代码。

private static DataTable DTTable(string mysqlQuery, string queryName)
{
    DataTable DTTableTable = new DataTable();
    try
    {
        MySqlDataAdapter DataDTTables = new MySqlDataAdapter(mysqlQuery, MySQLProcessing.MySQLStatic.Connection);
        DataTable DataDTTablesDT = new DataTable();
        DataDTTables.SelectCommand.CommandTimeout = 240000;
        DataDTTables.Fill(DataDTTablesDT);
        DTTableTable = DataDTTablesDT;

    }
    catch (Exception ex)
    {

        GenericLogging("Failed MySQLquery: " + ex.Message.ToString(), "MySQLProcessor", "DTTable", "", "MysqlError", "", queryName, mysqlQuery);

    }
    return DTTableTable;
}

private static void MySQLInsertUpdate(string MySQLCommand, string mysqlcommand_name)
{
    try
    {
        MySqlCommand MySQLCommandFunc = new MySqlCommand(MySQLCommand, MySQLProcessing.MySQLStatic.Connection);
        MySQLCommandFunc.CommandTimeout = 240000;
        MySQLCommandFunc.ExecuteNonQuery();
    }
    catch (Exception ex)
    {
        GenericLogging("Failed MySQLquery: " + ex.Message.ToString(), "MySQLProcessor", "DTTable", "", "MysqlError", "", mysqlcommand_name, MySQLCommand);
    }
}

事实上,WCC包含大约10个空洞,每个空洞至少访问一次MySQL函数。因此,如果锁定是答案,是否可能为所有空洞创建一个锁定函数?如果有其他方法,请告诉我。谢谢!
好的,如建议所述,我整合了问题。
代码现已更新以反映锁定,请参见以下内容。 static readonly object _object = new object(); 这是唯一调用DataReader的代码,如果有锁,怎么可能存在两个打开的DataReader呢?

如果我没记错的话,问题出在返回 DataTable 的方法上,而不是返回 void 的方法上。你可以实现一个连接池来解决这个问题。 - phoog
2个回答

2
问题在于,ADO.NET数据提供程序通常不允许每个连接同时打开多个数据读取器。SQL Server有“多活动结果集(MARS)”的概念,但据我所知,MySQL尚不支持它。
您可能需要指定一个与MySQLProcessing.MySQLStatic.Connection不同的连接。这里没有任何阻止您使用多个连接。问题在于连接是昂贵的资源,因此您应该节约使用它们。

0

您同时在使用相同的连接。

您是否有多个线程?因为似乎有2个线程同时使用相同的连接并发地进行调用。


1
上面贴的代码中没有锁。但是你确定这是你使用此连接的唯一方法吗?此外,您可以创建多个连接,因为.NET具有连接池,如果已经有一个连接可用,则不会创建新连接,这样成本就很低了。 - Fabske
2
Fabske,你可能认为你需要5个投票才能关闭自己的问题。 - user222427
Fabske我为每个线程使用一个连接,但没有其他代码在使用它。 - user222427
3
我不明白。所有这些都可以通过不使用静态连接来避免。 - Chris Farmer
1
不是这样的。你使用它,处理完毕就可以了。using (var conn = CreateSomeConnection()) { /* 使用它 */ }。这是一个连接。 - Chris Farmer
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接