vb.net - (假设)异步查询等待结果
问题描述
我的目的是查询远程数据库,在许多(最多 5000 个)表中查询单个(但每个表不同)字段:
SELECT FOO FROM TABLEA WHERE ...
SELECT BAR FROM TABLEB WHERE ...
到目前为止,使用的代码是:
Public Class ValuesRepository
Private connectionString As String
Private BatchOdbcConnection As IDbConnection
Public Sub New(connectionString As String)
Me.connectionString = connectionString
BatchOdbcConnection = New Odbc.OdbcConnection("DRIVER={AspenTech ODBC driver for Production Record Manager};" + connectionString)
End Sub
PublicFunction GetAllBatchValues(tagList As IEnumerable(Of BatchTag)) As IEnumerable(Of IEnumerable(Of Double?))
Dim returnList As New List(Of IEnumerable(Of Double?))
If tagList.Count = 0 Then Return returnList
BatchOdbcConnection.Open()
For Each batchTag In tagList
Dim result As Double? = GetBatchList(batchTag.fieldName, batchTag.tableName)
If result Is Nothing Then
Continue For
Else
returnList.Add(result.Value)
End If
Next
BatchOdbcConnection.Close()
Return returnList
End Function
Private Function GetBatchList(fieldName As String, tableName As String) As IEnumerable(Of Double?)
Const SQLQuery As String = "SELECT ""{0}"" FROM ""{1}"";"
Dim query = String.Format(SQLQuery,
fieldName,
tableName)
Dim queryResult = BatchOdbcConnection.Query(Of Double?)(query, commandType:=CommandType.Text)
Return queryResult
End Function
End Class
我已经对代码进行了概要分析,在 Dapper 的方法中,多达 70% 的时间都在等待,Query
效率相当低。
我一直在尝试通过使其全部异步来改进这一点,以便在完成之前启动下一个查询:
Public Class ValuesRepository
Private connectionString As String
Public Sub New(connectionString As String)
Me.connectionString = connectionString
End Sub
Private Function GetOdbcConnection() As IDbConnection
Return New Odbc.OdbcConnection("DRIVER={AspenTech ODBC driver for Production Record Manager};" + connectionString)
End Function
Public Function GetAllBatchValues(tagList As IEnumerable(Of BatchTag)) As IEnumerable(Of IEnumerable(Of Double))
Dim returnList As New List(Of IEnumerable(Of Double?))
If tagList.Count = 0 Then Return returnList
Dim tasks As New List(Of Task(Of IEnumerable(Of Double?)))
For Each batchTag In tagList
tasks.Add(GetBatchList(batchTag.fieldName, batchTag.tableName))
Next
Task.WaitAll(tasks.ToArray())
For Each task In tasks
Dim result = task.Result
If result Is Nothing Then
Continue For
Else
returnList.Add(result.Value)
End If
Next
Return returnList
End Function
Private Async Function GetBatchList(fieldName As String, tableName As String) As Task(Of IEnumerable(Of Double?))
Console.WriteLine("Begin " + fieldName + " -> " + tableName)
Using conn = GetOdbcConnection()
Const SQLQuery As String = "SELECT ""{0}"" FROM ""{1}"";"
Dim query = String.Format(SQLQuery,
fieldName,
tableName)
Dim queryResult = Await conn.QueryAsync(Of Double?)(query, commandType:=CommandType.Text)
Console.WriteLine("End " + fieldName + " -> " + tableName)
Return queryResult
End Using
End Function
End Class
我一直期望它启动所有查询,然后等待结果,因此在控制台中读取如下内容:
Begin: Foo -> TableA
Begin: Bar -> TableB
...
End: Bar -> TableB
End: Foo-> TableA
相反,控制台显示:
Begin: Foo -> TableA
End: Foo-> TableA
Begin: Bar -> TableB
从节奏中可以清楚地看出,应用程序实际上是在每次调用后等待查询结束。
我究竟做错了什么?
解决方案
尝试用 Await Task.Delay 替换 Await conn.QueryAsync ,看看是否可行。如果它确实有效,那么您会遇到一个新问题“为什么 Await conn.QueryAsync 会阻止所有活动任务?”。检查您的驱动程序版本是否支持异步调用。可能有一个名为 QueryAsync 的方法,但在后面,它调用了一个不支持 Async 的驱动程序。
推荐阅读
- python - 使用置信区间可视化 2D 嵌入
- c - 从特定地址初始化多维数组指针的正确方法
- python - 需要一个条件语句来填充基于字符串的列
- azure-devops - Azure DevOps 无法从其自己的存储库下载工件
- php - 如何在选择中显示分组项目?
- android - 将数字四舍五入到下一个最高的位置
- node.js - 默认 Firebase 应用不存在。确保在使用任何 Firebase 服务之前调用 initializeApp()。在 FirebaseAppError
- node.js - 无法通过 REST API 访问使用 Mongodb 部署的 Nodejs 应用程序
- php - 如何每 5 秒更新一次显示的用户的离线、在线状态?
- java - Java - poi:将一个 docx 附加到另一个 docx 时出现问题:使用未定义的命名空间 > 前缀:w15