C#Parallel.ForEach从池中打开太多连接

时间:2016-12-09 14:27:04

标签: c# mysql foreach parallel-processing mariadb

收到的完整错误是:

Timeout expired.  The timeout period elapsed prior to obtaining a connection from the pool.  This may have occurred because all pooled connections were in use and max pool size was reached.

所以我有一个平行的foreach:

      Parallel.ForEach(fields, item =>
        {
            item.SysInvoiceID = _destinationRepo.GetMySQLSystemID(item);
        });

调用一个如下所示的方法:

   public int GetMySQLSystemID(CustomFieldBase GenericCustomField)
        {
            CustomField customField = GenericCustomField as CustomField;
            int sys_InvoiceID = 0;
            using (MySqlConnection mySQLConnection = new MySqlConnection("Server=web01;Database=wmp;User Name=root;Password=TotallyMyPWord"))
            {
                using (MySqlCommand cmd = new MySqlCommand())
                {
                    cmd.CommandText = $@"SELECT Sys_InvoiceID FROM tblsys_naturalkey_lu WHERE CompanyCode = '{customField.CompanyCode}' AND InvoiceNo = '{customField.InvoiceNo}'
                                            AND LineItemNo = '{customField.LineItemNo}' AND FiscalYear = '{customField.FiscalYear}'";
                    cmd.CommandType = CommandType.Text;
                    cmd.Connection = mySQLConnection;

                    mySQLConnection.Open();

                    using (var reader = cmd.ExecuteReader())
                    {
                        if (reader.Read())
                        {
                            sys_InvoiceID = (int)reader["Sys_InvoiceID"];
                        }
                    }
                    mySQLConnection.Close();
                }
            }
            return sys_InvoiceID;
        }

在查看MySQL会话管理器时,我可以看到Parallel.ForEach在我达到限制之前不断添加连接。

我关闭了我的MySQLConnection,为什么它一直在创建连接直到最大限制?

2 个答案:

答案 0 :(得分:0)

您对Parallel.ForEach()创建的并行操作数量没有任何限制,因此它将创建无限数量的SQL连接。

您可以通过specifying the maximum degree of parallelism

解决此问题
Parallel.ForEach(fields, new ParallelOptions { MaxDegreeOfParallelism = 8 }, item =>
{
    item.SysInvoiceID = _destinationRepo.GetMySQLSystemID(item);
});

然而(正如其他人所指出的那样),在任何情况下,你都不应该使用Parallel.ForEach()进行IO绑定工作。

答案 1 :(得分:0)

您可以使用SqlConnection.ClearPool方法,但如果必须通过并行循环执行此操作,我仍建议重用您的连接。正如其他人所说,你不应该这样做。

例如,在启动并行循环之前打开连接。一切都完成后再处理。