1

.Net 3.5 アプリケーションで DataTable を使用して、ファイル名を含むいくつかのレコードを含む 1 つの列を格納しています。

DataTable を初期化する方法と場所に関するコードを次に示します。

public partial class MainForm : Form
{
    DataTable memTable_CurrentTransfers = new DataTable();


private void MainForm_Load(object sender, EventArgs e)
{
    memTable_CurrentTransfers.Columns.Add("fileName", typeof (string));


アプリケーションの別のメソッドでファイル名を DataTable に追加する方法は次のとおりです。

memTable_CurrentTransfers.Rows.Add(fileName);


30 分ごとに、次のコードを実行するスレッドを起動します。

public void CheckUploads()
{
   DataView view2 = memTable_CurrentTransfers.DefaultView;

   for (int i = 0; i < view2.Count; i++)
   {
     string tmpString = view2[i][0].ToString();


すべてがうまく機能しますが、アプリケーションをしばらく実行した後、ユーザーは CheckUploads() メソッドでこのエラーを受け取り始めています

指定されたキーはディクショナリに存在しませんでした。System.ThrowHelper.ThrowKeyNotFoundException() で System.Collections.Generic.Dictionary`2.get_Item(TKey キー) で System.Data.DataView.get_Item(Int32 recordIndex) で


私の列が DataTable から消えていると思います。

なぜこれが起こっているのか、どうすればこれを防ぐことができるのか教えてください。アプリケーション内のすべてのメソッドから使​​用できるように、DataTable を初期化する別の方法はありますか?

4

1 に答える 1

1

まず、aDataTableはスレッドセーフではなく、投稿したコードには同期が含まれていません。

「同期は含まれていません」について詳しく教えてください。

DataTable:にアクセスする複数のスレッドがあると言います。CheckUploadsメソッドはバックグラウンドスレッド上にあり、おそらく、メインスレッドに行を追加(および場合によっては削除)するコードがあります。

同期が不要になるようにアプリケーションを設計することをお勧めします。たとえば、メインのクローンをDataTableバックグラウンドスレッドに渡して、同じインスタンスにアクセスするスレッドが複数存在しないようにします。

私の列がDataTableから消えていると思います。

その証拠は見当たりません。スタックトレースはSystem.Data.DataView.get_Item(Int32 recordIndex)、列ではなく行()が見つからないことを示しているようです。

ebyrobのコメントから:

lock(memTable_CurrentTransfers){memTable_CurrentTransfers.Rows.Add(filename)}およびmemTable_CurrentTransfersへの他のすべてのアクセスと同様。

また、へのアクセスには同じロックを使用する必要がありますDataView。同期を間違えるのは簡単ですが、同期が不要になるようにアプリを設計することをお勧めします。

于 2012-10-08T17:25:56.643 に答える