私は、C# で .NET WinForms アプリを使用して、3.5 .NET フレームワークに対して実行しています。このアプリでは、 a の .Expression メンバーを次のように設定してDataColumn
いDataTable
ます。
DataColumn column = dtData.Columns["TestColumn"];
column.Expression = "some expression";
実際に を設定した 2 行目Expression
で、次の例外が発生することがあります。
FileName=
LineNumber=0
Source=System.Data
TargetSite=Int32 RBInsert(Int32, Int32, Int32, Int32, Boolean)
System.InvalidOperationException: DataTable internal index is corrupted: '5'.
at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
at System.Data.Index.InitRecords(IFilter filter)
at System.Data.Index.Reset()
at System.Data.DataTable.ResetInternalIndexes(DataColumn column)
at System.Data.DataTable.EvaluateExpressions(DataColumn column)
at System.Data.DataColumn.set_Expression(String value)
エラーがいつ発生するかについて、認識できるリズムや理由はありません。同じデータセットをロードすると、正常に機能する場合がありますが、再ロードすると失敗します。その逆も同様です。DataTable
これは、列の1つを変更しようとしているときに別の書き込み操作が発生している競合状態に関連していると思われます。DataTable
ただし、 s に関連するコードはマルチスレッド化されておらず、UI スレッドでのみ実行されます。
Web およびMicrosoft フォーラムを検索しましたが、この問題について多くの議論と混乱が生じています。この問題が最初に報告された 2006 年には、これは .NET フレームワークの欠陥であると考えられており、.NET フレームワークの新しいバージョンに組み込まれたと思われる修正プログラムがいくつかリリースされていました。ただし、現在のフレームワークには適用できなくなったこれらの修正プログラムを適用した結果がまちまちであると報告されています。
もう 1 つの有力な理論は、DataTable には操作があり、一見無害に見えますが、実際には書き込み操作であるというものです。たとえば、 にDataView
基づいて新しい を作成することは、後で参照DataTable
するために に内部インデックスを作成するため、実際にはテーブル自体に対する書き込み操作です。DataTable
これらの書き込み操作はスレッド セーフではないため、DataTable
. これにより、の内部インデックスがDataTable
破損し、例外が発生します。
lock
コード内の各作品の周りにブロックを配置しようとDataView
しましたが、前述のように、 を使用するコードDataTable
はスレッド化されlock
ておらず、いずれにせよ s は効果がありませんでした。
誰かがこれを見て、うまく解決/回避しましたか?
いいえ、残念ながらできません。DataTable のロードは、DataColumn の 1 つに Expression を適用するために DataTable を取得するまでに既に発生しています。列を削除してから、提案されたコードを使用して再度追加することはできますが、内部インデックスが破損しているという問題を解決する特定の理由はありますか?