简体   繁体   English

使用 ExecuteNonQuery 时 Parallel.Foreach 死锁?

[英]Deadlock in Parallel.Foreach while using ExecuteNonQuery?

I am facing deadlock error while using Parallel.Foreach.我在使用 Parallel.Foreach 时遇到死锁错误。 I have 1000 records in datatable and i'hv created 5 threads to process it.我在数据表中有 1000 条记录,我创建了 5 个线程来处理它。 but when i'hv run this console application then after some records processed it will create a deadlock and no other records will process.但是当我运行这个控制台应用程序时,在处理了一些记录之后,它会创建一个死锁,并且不会处理其他记录。 Here is my code:这是我的代码:

Parallel.ForEach(dt1.AsEnumerable(), new ParallelOptions { MaxDegreeOfParallelism = 5 }, dr =>
{
    cmd1.CommandText = $"Update AuditMessage set Status=1" +
        $" where SXAEASCoreAuditMessageID ='{Convert.ToString(dr["AuditMessageID"])}' ";
    cmd1.CommandType = CommandType.Text;
    cmd1.Transaction = trans;
    cmd1.ExecuteNonQuery();                          
});

Why does it lock?为什么会锁定?

Your problem is probably not database concurrency, but concurrency on the cmd1 object, which you are using for every thread.您的问题可能不是数据库并发,而是您用于每个线程的 cmd1 object 上的并发。

You need to create a new SqlCommand for each of the threads, or in every iteration.您需要为每个线程或在每次迭代中创建一个新的 SqlCommand。

Parallel.ForEach(dt1.AsEnumerable(), new ParallelOptions { MaxDegreeOfParallelism = 5 }, dr =>
    {
                  using(var cmd = new SqlCommand(connection))
                  {
                     cmd.CommandText = $"Update AuditMessage set Status=1 where SXAEASCoreAuditMessageID ='{Convert.ToString(dr["AuditMessageID"])}' ";
                     cmd.CommandType = CommandType.Text;
                     cmd.Transaction = trans;
                     cmd.ExecuteNonQuery();
                  }                          
    });

some basics on row/table locking.行/表锁定的一些基础知识。

In case you are doing is on SQL Server, you are creating more overhead than speed out of this parallel processing.如果您在 SQL 服务器上执行此操作,那么您在此并行处理中创建的开销大于速度。 Every row modified will be locked by the DBMS, and eventually, when the overhead gets to high, it will commence a table lock, leaving your threads working sequentially anyway.修改的每一行都将被 DBMS 锁定,最终,当开销变高时,它将开始一个表锁定,让您的线程无论如何都按顺序工作。

so, forget about parallel.foreach here, and let the database do the efficiency optimizing所以,这里忘了parallel.foreach,让数据库做效率优化

You could select the AuditMessageIds into a List.您可以 select 将 AuditMessageIds 放入一个列表中。 Then cut it to pieces of 100 or so, and then make a smarter update query, like a query which does the update to status 1 in bulks..然后将其切成 100 块左右,然后进行更智能的更新查询,例如批量更新状态 1 的查询。

where SXAEASCoreAuditMessageID IN ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM