1

我有一个用 C# 编写的多线程 TCP 服务器软件。许多线程应该从数据库中读取,我正在使用 SqlDataReader 从数据库中读取。当一个线程想要从数据库中读取时,没有问题,但是当两个或更多线程想要从数据库中读取时,这种情况就开始出现问题了。.NET 给出了这个例外:已经有一个打开的 DataReader 与此命令关联,必须先关闭它。

我怎样才能防止错误?如何保护 SqlDataReader 免受多次访问?互斥锁适合这个问题吗?

4

3 回答 3

3

如何保护 SqlDataReader 免受多次访问?

甚至不共享连接。

SqlConnection为每个数据库操作创建一个新的(在using操作结束时处理它的语句中),并让连接池处理以提高效率。

如果您不共享连接,则不会出现此错误,也不会通过锁定序列化您的数据库访问。

于 2012-05-01T08:28:10.300 回答
3

您应该向 .net 运行时询问每个线程内的新 sql 连接。就速度而言,这是最佳解决方案(这使用 .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!
         }
    }
}

如果我有一些示例代码来展示您当前拥有的内容,我可以根据您的情况调整该想法。

至于锁定,如果你真的想走这条路(说真的,不要),你需要做的就是锁定(基本同步原语之一):

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 回答