1

私は C# で書かれたマルチスレッド TCP サーバー ソフトウェアを持っていました。スレッドの多くはデータベースから読み取る必要があり、データベースからの読み取りに SqlDataReader を使用しています。1 つのスレッドがデータベースから読み取りたい場合は問題ありませんが、2 つ以上のスレッドがデータベースから読み取りたい場合、この状況が問題になり始めます。.NET では次の例外が発生します。この Command に関連付けられている DataReader が既に開いているため、最初に閉じる必要があります。

どうすればエラーを防ぐことができますか? SqlDataReader を多重アクセスから保護するにはどうすればよいですか? ミューテックスはこの問題に適していますか?

4

3 に答える 3

3

SqlDataReaderを複数のアクセスから保護するにはどうすればよいですか?

接続を共有することさえしないでください。

SqlConnectionデータベース操作ごとに新しいものを作成し(操作usingの最後にそれを破棄するステートメントで)、これを効率的にするために接続プールに処理させます。

接続を共有していない場合、このエラーが発生することはなく、ロックを介してデータベースアクセスをシリアル化することもありません。

于 2012-05-01T08:28:10.300 に答える
3

各スレッド内で新しいSQL接続を.netランタイムに要求する必要があります。これは、速度に関する限り最適なソリューションです(これは、.netのSQL接続プールを使用するため、接続の確立に時間を費やすことはありません)。

于 2012-05-01T08:29:01.610 に答える
2

既存のアクティブな接続を再利用しようとするのではなく、リクエストごとに新しい接続を作成することをお勧めします。ある種のクラスメンバーまたは接続への静的参照を使用していると仮定します。代わりに、メソッドスコープにします。

private void RespondingToTcpRequest()
{
    using (var connection = new SqlConnection(""))
    using (var command = new SqlCommand("", connection))
    {
         connection.Open();

         using (var reader = command.ExecuteReader())
         {
             // No locks or sharing issues here!
         }
    }
}

あなたが現在持っているものを示すサンプルコードがあれば、そのアイデアをあなたの状況に適応させることができます.

ロックに関しては、本当にこのルートをたどりたい場合 (真剣に、そうしないでください)、必要なのはロック (基本的な同期プリミティブの 1 つ) だけです。

private static readonly object ReaderLock = new object();

private void RespondingToTcpRequest()
{
    lock (ReaderLock)
    {
        // database connection, command, reader stuff here.
    }
}

問題はプロセスローカルであり、lock キーワードで十分であるため、ミューテックスは必ずしも必要ではありません。繰り返しますが、真剣に、しないでください。

于 2012-05-01T08:26:48.810 に答える