2012-04-26 95 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方法线程安全吗?

不,它不是。每次输入方法时,都会在新对象上创建锁定。您锁定的对象必须在所有线程中都是相同的,否则锁永远不会被视为“被占用”,因为每个线程都会愉快地为之后抛弃的对象创建新的锁。实现这一点的一种方法是让你锁定的对象也是静态的。