从同一个线程多次调用 sub

Posted

技术标签:

【中文标题】从同一个线程多次调用 sub【英文标题】:calling sub multiple times from same thread 【发布时间】:2019-10-29 16:27:00 【问题描述】:

我有一个单线程应用程序,它需要多次调用 sub 并每次传递不同的参数。唯一的问题是子打开一个数据读取器并从数据库中读取数据(使用传递的参数)。这工作正常,但读取操作需要几秒钟,所以对 sub 的第二次调用会引发错误“已经有一个打开的数据读取器与此连接关联”。

如果不重新设计我的整个应用程序,我是否缺少一些我需要对数据读取器执行某些操作以允许同时发生多个读取的地方?

谢谢。

例如:

For x as integer = 0 to 10
 dim id as integer = my_sub(x)
Next X

Private function my_sub(x)

  dim return_value as integer = 0

  my_reader = sqldatareader
  db.cmd.CommandText = "select id from database where id = " & x
  my_reader = db.cmd.ExecuteReader
  my_reader.Read()
  If my_reader.HasRows Then
     return_value = my_reader(0)
  End If
  my_reader.Close()

  Return return_value

End Sub

【问题讨论】:

如果没有看到代码,您的问题可能会作为Exception: There is already an open DataReader associated with this Connection which must be closed first 的副本而被关闭。 我添加了一些代码。 需要注意的是这段代码有一个巨大的安全漏洞并且对SQL注入开放 Andrew Morton 的链接可以解决您的问题。您的命令,可能还有您的连接,不限于my_sub()。您应该在需要时实例化您的连接和命令对象,然后处理它们。您的已经实例化(并且连接打开),包装在变量db 中。这就是导致问题的原因。 这能回答你的问题吗? Exception: There is already an open DataReader associated with this Connection which must be closed first 【参考方案1】:

用户HardCode在their comment提供了很好的解释:

您的命令,可能还有您的连接,不限于my_sub()。您应该在需要时实例化您的连接和命令对象,然后处理它们。你的已经实例化了(并且连接打开了),包装在变量db中。这就是导致问题的原因。

相应的代码会是这样的

Private Function MySub(x As Integer) As Integer

    Dim returnValue As Integer = 0

    Using conn As New SqlConnection(yourConnectionString)
        Dim sql = "SELECT [id] FROM [database] WHERE [id] = @x"

        Using cmd As New SqlCommand(sql, conn)
            cmd.Parameters.Add(New SqlParameter With .ParameterName = "@x", .SqlDbType = SqlDbType.Int, .Value = x)

            conn.Open()
            Dim rdr = cmd.ExecuteReader()

            If rdr.HasRows Then
                rdr.Read()
                returnValue = rdr.GetInt32(0)
            End If

            rdr.Close()
            conn.Close()

        End Using
    End Using

    Return returnValue

End Function

【讨论】:

是的,我现在看到每次调用 sub 时都需要一个单独的(和新的)连接。所以 sub 需要包含连接的新实例,并且我不能使用在 sub 之外创建的现有连接。谢谢您的帮助。现在可以使用了。

以上是关于从同一个线程多次调用 sub的主要内容,如果未能解决你的问题,请参考以下文章

Parallel Make - 多次调用子项目

一个线程多次调用一个函数

用面向对象重写thread 实现多次调用一个线程

避免多次调用 Invoke 以从另一个线程更新 GUI

在线程上多次调用 start() 会发生啥[关闭]

Java - java线程可以多次调用启动吗?