2

DataTable/DataSet への更新操作をスレッドセーフにしたいと考えています。DataTable のメソッドを使用してグローバル DataTable の最大 40 行をそれぞれ更新する最大 20 のスレッドがありRows.Find(pk)ます。各スレッドは、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

2 に答える 2

6

いいえ、安全ではありません。次のコードを変更する必要があります。

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はロックされた部分にいるはずです。

于 2012-04-26T16:29:51.237 に答える
1

UpdateRow メソッドはスレッドセーフですか?

いいえ、ちがいます。メソッドに入るたびに、新しいオブジェクトにロックを作成しています。ロックするオブジェクトは、すべてのスレッドで同じである必要があります。そうしないと、各スレッドが後で破棄するオブジェクトに新しいロックを喜んで作成するため、ロックが「取得された」とは見なされません。これを実現する 1 つの方法は、ロックするオブジェクトも静的にすることです。

于 2012-04-26T16:29:45.070 に答える