0

在这里的第一个计时器,所以对我放轻松。理论上是否可以同时在单独的线程上执行两个 OleDBDataAdapter.Fill 调用 - 还是从根本上存在缺陷?

考虑一个带有 2 个按钮和 2 个数据网格视图的表单。每次单击按钮都会使用 Async \ Await \ Task.Run 模式启动一个工作线程,该模式调用一个方法以返回填充的数据表并将其分配给其中一个数据网格视图。第一个线程中的 .Fill 需要 30 秒才能完成。第二个线程中的 .Fill 需要 1 秒才能完成。单独启动时,两个按钮都按预期工作。

但是,如果我启动第一个工作线程(填充 30 秒),然后启动第二个线程(1 秒填充),则在第一个 .Fill 调用完成之前不会填充第二个 DataGridView。我预计第二个 datagridview 将在 1 秒内填充,而第一个 datagridview 将在大约 30 秒后填充。

我在我的示例代码中使用 OleDBDataAdapter 和 SqlDataAdapter 复制了这个问题。如果我用一个简单的 Thread.Sleep(30000) 替换长时间运行的查询,第二个 datagridview 会立即填充。这让我相信这不是我的设计模式的问题,而是特定于同时发出 .Fill 调用的问题。

Private Async Sub UltraButton1_Click(sender As Object, e As EventArgs) Handles UltraButton1.Click

    Dim Args As New GetDataArguments
    Args.ConnectionString = "some connection string"
    Args.Query = "SELECT LongRunningQuery from Table"

    Dim DT As DataTable = Await Task.Run(Function() FillDataTable(Args))
    If DataGridView1.DataSource Is Nothing Then
        DataGridView1.DataSource = DT
    Else
        CType(DataGridView1.DataSource, DataTable).Merge(DT)
    End If

End Sub

Function FillDataTable(Args As GetDataArguments) As DataTable

    Dim DS As New DataTable

    Using Connection As New OleDbConnection(Args.ConnectionString)
        Using DBCommand As New OleDbCommand(Args.Query, Connection)
            Using DataAdapter As New OleDbDataAdapter(DBCommand)
                DataAdapter.Fill(DS)
            End Using
        End Using
    End Using

    Return DS

End Function

Private Async Sub UltraButton2_Click(sender As Object, e As EventArgs) Handles UltraButton2.Click

    Dim DS As DataTable = Await Task.Run(Function() LoadSecondDGV("1234"))
    DataGridView2.DataSource = DS

End Sub

Function LoadSecondDGV(pnum As String) As DataTable

    Dim DX As New DataTable

    Using xConn As New OleDbConnection("some connection string")
        Using DataAdapter As New OleDbDataAdapter("Select name from products where PNUM = """ & pnum & """", xConn)
            DataAdapter.Fill(DX)
        End Using
    End Using

    Return DX

End Function
4

1 回答 1

0

这取决于数据源是什么。某些数据源(如 Excel)一次只允许一个连接。其他数据源(如 Access)将允许多个连接,但实际上以串行方式完成结果,这样您就不会获得任何东西。其他数据源,如 Sql Server,将允许您正在寻找真正的并行活动。

在这种情况下,您提到您还尝试使用 SqlDataAdapter,这向我表明您正在与 Sql Server 对话,这应该是可能的。这里可能发生的是,您的第一个查询锁定了第二个查询所需的一些数据。您可以通过更改事务隔离级别或仔细使用with (nolock)提示(强烈首选前一个选项)来解决此问题。

要记住的另一件事是,这只有在您为每个查询使用单独的连接,或者如果您专门启用了多个活动结果集功能时才有效。看起来你在这里使用了单独的连接对象,所以你应该没问题,但我认为这仍然是值得提出的。

最后,我需要对您的FillDataTable()方法发表评论。此方法要求您提供完整的 Sql 字符串,这实际上迫使您编写极易受到 sql 注入攻击的代码。继续使用所示的方法实际上可以保证您的应用程序将被黑客入侵,可能迟早会被黑客入侵。您需要修改此方法,以鼓励您使用参数化查询。

于 2014-04-24T21:28:41.240 回答