我有一个静态方法,它在Parallel.ForEach循环中的静态方法中调用SQL SP。 SP在3个不同的表中插入数据。我正在使用Serializable Transaction级别。但有一段时间我遇到了僵局的情况。
我在想,如果我将该方法作为Instance方法或使用简单的ForEach,它可能会解决问题。
我在想什么?我是否也需要锁定列表?
- 代码 -
Parallel.ForEach(MyConcurrentDictionary, MyElement =>
{
if (MyElement.SomeProperty != SomeValue)
{
PublishMessage(MyElement);
}
else
{
InsertInDatabase(MyElement);
}
}
public static void InsertInDatabase()
{
DataTable t1 = new DataTable();
DataTable t2 = new DataTable();
DataTable t3 = new DataTable();
CreateTable(T1);
CreateTable(T2);
CreateTable(T3);
using (var conn = new SqlConnection(ConnString))
{
try
{
conn.Open();
// Begin transaction
using (SqlTransaction transaction = conn.BeginTransaction(IsolationLevel.Serializable))
{
SqlCommand cmd = new SqlCommand();
cmd.Transaction = transaction;
cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SPName";
cmd.Parameters.AddWithValue("@T1", T1);
cmd.Parameters.AddWithValue("@T2", T2);
cmd.Parameters.AddWithValue("@T3", T3);
cmd.ExecuteNonQuery();
transaction.Commit();
}
}
}
}
答案 0 :(得分:1)
尝试将您的类更改为非静态方法,这将有很大帮助。永远不要同时使用静力学它只是在寻找麻烦。为了安全起见,尝试使用线程保存列表,即同步化的arraylist或System.Collections.Concurrent.ConcurrentQueue(Of T)
。
亲切的问候
答案 1 :(得分:0)
由于您不使用任何同步,因此会出现问题。关键字static
并不意味着它是线程安全的。来自Parallel.ForEach
的多个线程仍然可以同时访问此方法。
你有很多选择来同步它。但我将从最简单的一个开始,使其成为单线程。如果无法使用,请使用lock
或查看other options
UPDATE
正如@Colin所注意到的,如果你在某处更新数据,我的答案是有效的。如果一切都是只读的,那么还有其他的东西。检查DataTable的创建。