2012-04-26 41 views
0

我想對DataTable/DataSet進行線程安全更新操作。有大約20個線程使用DataTable的Rows.Find(pk)方法更新〜40行全局DataTable。每個線程將更新不同的DataTable行。線程安全的數據集

我爲DataSet使用以下包裝類。這種方法是線程安全的嗎?

public sealed class MyDataSet{ 

    public static DataSet ds = new DataSet(); 

    public static UpdateRow(key,data) 
    { 
     object _lock = new object(); 
     DataRow dr = ds.Tables[0].Rows.Find(key); 
     lock(_lock){   
      dr.AcceptChanges(); 
      dr.BeginEdit(); 
      dr["col"] = data; 
      dr.EndEdit(); 
     } 
    } 
} 

該方法從for循環中調用。

for(int x=0; x<40; x++;){ 
    if(someCondition) 
    . 
    . 
    . 
    MyDataSet.UpdateRow(key,data); 
    . 
    . 
    . 
    } 

一切都在多線程環境中完成。 UpdateRow方法是否線程安全?

回答

4

不,它不安全。你應該改變你的代碼:

public sealed class MyDataSet{ 

    public static DataSet ds = new DataSet(); 

    private static object _lock = new object(); 

    public static UpdateRow(key,data) 
    { 
     lock(_lock){ 
      DataRow dr = ds.Tables[0].Rows.Find(key); 
      dr.AcceptChanges(); 
      dr.BeginEdit(); 
      dr["col"] = data; 
      dr.EndEdit(); 
     } 
    } 
} 

_lock對象應該是在你的程序,使其一把好鎖的靜態對象。並且您的Find應該處於鎖定部分。

1

UpdateRow方法線程安全嗎?

不,它不是。每次輸入方法時,都會在新對象上創建鎖定。您鎖定的對象必須在所有線程中都是相同的,否則鎖永遠不會被視爲「被佔用」,因爲每個線程都會愉快地爲之後拋棄的對象創建新的鎖。實現這一點的一種方法是讓你鎖定的對象也是靜態的。