2011-06-01 47 views
2

我有一個靜態方法,它在Parallel.ForEach循環中的靜態方法內調用SQL SP。 SP將數據插入3個不同的表格中。我正在使用可序列化交易級別。但是偶爾我會遇到死鎖情況。Parallel.ForEach中的SQL查詢 - 死鎖

我在想,如果我將該方法作爲Instance方法或使用簡單的ForEach,它可能會解決問題。

我在想對不對?我是否也需要鎖定列表?

--Code--

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

你在一次交易中運行所有這一切嗎? – 2011-06-01 14:14:19

+0

@Johann Blais - 每個元素創建自己的交易。事務在Parallel.ForEach中創建。 – Asdfg 2011-06-01 14:16:55

+0

這可能不值得多線程。如果你正在做SQL插入,你可能會比CPU綁定更多的IO綁定。 – 2011-06-01 14:16:56

回答

0

,因爲你不使用任何同步你得到的問題。關鍵字static並不意味着它是線程安全的。來自Parallel.ForEach的多個線程仍可以同時訪問此方法。

您有許多選項可以實現同步。但我會從最簡單的一個開始,讓它成爲單線程。如果不可能,使用lock或看到other options

UPDATE
由於注意到了@Colin,如果你的地方更新數據我的回答工作。如果一切都是隻讀的,那麼還有其他的東西。檢查DataTable的創建。

+0

不一定。沒有任何顯示會導致C#代碼中的線程同步問題。 (但是,缺少可能有問題的代碼)。如果它不與其他線程共享數據(或者共享的任何數據只能在所有線程中純粹讀取),那麼同時調用靜態方法是非常好的 – 2011-06-01 19:33:17

+0

@Colin我認爲創建DataTable很可能是線程不安全的。 – oleksii 2011-06-01 20:10:10

+0

每一種方法都是靜態的。我討厭它,當人們這樣做的時候,製作方法實例方法更有意義。這些不是實用方法。這些方法執行數據庫操作。 – Asdfg 2011-06-01 20:36:22

1

嘗試將您的類更改爲非靜態方法,這將有很大幫助。切勿平行使用靜力學,它只是要求麻煩。爲了安全起見,請嘗試使用線程保存列表,即同步化陣列列表或System.Collections.Concurrent.ConcurrentQueue(Of T)

親切的問候