线程安全的数据集

时间:2012-04-26 16:26:09

标签: c# dataset thread-safety

我想对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方法线程安全吗?

2 个答案:

答案 0 :(得分:5)

不,这不安全。您应该在以下位置更改您的代码:

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 :(得分:1)

  

UpdateRow方法线程安全吗?

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