在这里的第一个计时器,所以对我放轻松。理论上是否可以同时在单独的线程上执行两个 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