1

電話すると次の例外が発生しますが、そのdatatable.Copy()理由がわかりません。この問題を回避するためにロックを適用しましたが、修正されていないようです。例外は常に発生するわけではないので、スレッドに関係していることはわかっています。ロックの仕組みを誤解していますか?

System.InvalidOperationException: コレクションが変更されました。列挙操作が実行されない可能性があります。System.Data.RBTree`1.RBTreeEnumerator.MoveNext() で System.Data.DataTable.Copy() で

コード:

DataTable dt;

lock (ClassName.datatable)
{
    dt = ClassName.datatable.Copy();
}

ClassNameは型であり、オブジェクトではありません (以前の質問で混乱がありました)。

4

1 に答える 1

3

コメントから判断すると、あなたは仕組みを誤解してlockいます。これは協調的なスキームであり、2 つのスレッドが同時に同じモニターのロックを保持することはできません。lockスレッドがステートメントまたはMonitor.Enter(および関連する呼び出し)を使用してロックに「入る」ことを試みない限り、別のスレッドがロックを保持しているという事実は関係ありません。

これは、鍵のないバスルームに「使用中」または「空いている」というサインがあるようなものです...誰もサインを自分で変更したり、現在の状態に注意したりすることを強制されることはありません...しかし、誰もが同意すれば両方を行うと、恥ずかしい状況を避けることができます。

個人的には、他のコードから見えるモニターでのロックを回避しようとしているので、おそらく次のようになります。

private readonly object tableLock = new objet();
private readonly DataTable table;

...

lock (tableLock)
{
    ...
}

少なくとも、テーブルを使用するすべての場所で潜在的にロックを取得する必要があります。もちろん、テーブルへの参照を格納する可能性のある他のメソッドに渡す場合、または他のコードによって与えられた場合、実際にはほとんど制御できません。それがどうなるかについて。

于 2012-06-20T16:47:52.030 に答える