2

DataTable多数のDataRows;を含むことができる があります。これDataTableには複数のスレッドからアクセスできます。一部のスレッドは、値を一部の行に変更することもできます。DataTable実際には、 をロックし、 を使用して検索しlinq、期待値を返す検索関数がいくつかあります。次のようなものです。

lock(tableContent)
{
    var t = (from row in tableContent.AsEnumerable()
            where row[fieldName] != DBNull.Value && row.Field<T>(fieldName).Equals(someValue) select row);
    if (t.Any())
    { ... }
}                     

問題は、 を複製 (オリジナルをロック)DataTableし、複製されたオブジェクトを検索した場合、ロックされた期間はオリジナルを直接検索するよりも高速になるかどうかです。

Cloning 操作は各行をコピーするのに O(n) かかると思うので、時間は検索と同じになりますが、クローン作成時間または同様のもの。

4

1 に答える 1

4

Clone は O(n) ですが、それだけではすべてがわかりません。クローンは、浅いクローン (テーブル内の参照をコピーするだけ) または深いクローン (オブジェクト自体をコピーする) にすることができます。ディープ クローンは、非常にコストのかかる操作になる可能性があります。検索時間も、1 つの整数フィールドだけをチェックする簡単な検索から、複数の値を比較するかなりコストのかかる複雑な検索までさまざまです。さらに、検索しているフィールドでデータがソートされている場合、検索は O(log n) であり、O(n) よりもかなり高速です。

誰かが行を追加、変更、または削除する可能性を考慮する必要がある場合は、ロックまたは複製する必要があります。単一の検索を実行している場合、クローンを作成するためにテーブルをロックする必要があるため、クローン作成はあまり意味がありません。また、検索に異常にコストがかかる場合を除き、クローン作成はおそらく検索よりも時間がかかります。

変更はまれで、検索は頻繁に行われるとおっしゃいました。その場合、無制限の数のリーダーまたは 1 つのライターをサポートするリーダー/ライター ロックを使用することをお勧めします。.NET では、おそらくReaderWriterLockSlimが必要です。それを使用すると、コードは次のようになります。

private ReaderWriterLockSlim tableLock = new ReaderWriterLockSlim();

public bool Search(string s)
{
    tableLock.EnterReadLock();
    try
    {
        // do the search here
        return result;
    }
    finally
    {
        tableLock.ExitReadLock();
    }
}

任意の数のリーダーが同時にテーブルを検索できます。もちろん、彼らがそれを変更しないという条件で。テーブルを変更する場合は、書き込みロックを取得する必要があります。

public void Modify(string s)
{
    tableLock.EnterWriteLock();
    try
    {
        // do the modification here
        return;
    }
    finally
    {
        tableLock.ExitWriteLock();
    }
}

スレッドが書き込みロックに入ろうとすると、既存のすべてのリーダーが終了するまで待機する必要があります。書き込みロックが要求された後に入ってくるリーダーは、既存のリーダーが終了し、ライターがロックを取得して解放するまで待機する必要があります。

リーダー/ライターのロックは、あなたが説明したのと同様の状況、つまり頻繁な読み取りとまれな書き込みで私にとって非常にうまく機能します。テストが非常に簡単なので、他に何もないとしても、調べる価値があります。

リーダー/ライター ロックは、可能であれば複数のリーダーを許可するため、検索と更新がほぼ等しい場合でもうまく機能します。考えてみると、可能であれば複数の読み取りが許可されるため、書き込みがはるかに頻繁に行われる場合でもうまく機能します。ReaderWriterLockSlim検索および更新できるデータ構造がある場合は、ほとんどの場合に使用します。

他にも解決策はありますが、実装と保守がはるかに困難なカスタム データ構造が含まれます。リーダー/ライター ロックを試してみることをお勧めします。その後、プロファイリングにより、スレッドがまだロックを待機しており、アプリケーションの応答時間が遅くなっていることが示されている場合は、代替手段を検討できます。

ただ、あなたが検索以上のことをしていることが少し心配です。あなたのサンプルは一連の行を選択し、それからあなたはif (t.Any()) { ... }. その中で何をしているの{ ... }ですか?時間がかかる場合は、選択した行だけをコードで複製することをお勧めします。その後、データ構造にアクセスする必要がある他のスレッドに影響を与えることなく、結果セットのロックとパーティーを心ゆくまで解放できます。

于 2013-07-19T14:26:52.667 に答える