问题
I am facing deadlock error while using Parallel.Foreach. I have 1000 records in datatable and i'hv created 5 threads to process it. 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();
});
回答1:
Why does it lock?
Your problem is probably not database concurrency, but concurrency on the cmd1 object, which you are using for every thread.
You need to create a new SqlCommand for each of the threads, or in every iteration.
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. 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.
so, forget about parallel.foreach here, and let the database do the efficiency optimizing
You could select the AuditMessageIds into a List. 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..
where SXAEASCoreAuditMessageID IN ...
来源:https://stackoverflow.com/questions/61673300/deadlock-in-parallel-foreach-while-using-executenonquery