vb.net - 控制异步操作的数量
问题描述
我有一个程序可以下载大约 500 个 url 并将它们保存在 SQLite Db 中。在我的程序中,我将这 500 个 url 分成更小的包(每个包大约 40 个 url),然后以 5 秒的间隔一个接一个地下载包(使用计时器控制),这样整个 500 个 url 将每分钟下载一次。
这是我获取数据的方法,为每个 url 调用。它使用 httpClient,在 Form_Load 中定义:
Private Async Function GetTseData(address As String) As Task(Of String)
Dim response As HttpResponseMessage = Await hc.GetAsync(address)
Dim Str = Await response.Content.ReadAsStringAsync()
If response.IsSuccessStatusCode Then
Return Str
Else
Return ""
End If
End Function
我的问题是有时在数据库中我会看到缺陷数据。例如,在下图中一个 url 的图像中,在 10:16 和 10:25 之间的大约 10 分钟内没有下载数据,然后突然之间我看到大约 10 个同时保存的数据(在 10:27)。正如我所说,每行之间必须有 1 分钟的间隔。
(tget 是保存在数据库中的时间。t1 和 t2 是调用上述方法之前和之后的时间)。
听起来我对异步操作的理解有问题。有什么提示吗?
编辑:这是我在 Timer_tick 中的简化代码:
Private Async Sub timerGetData_Tick(sender As Object, e As EventArgs) Handles timerGetData.Tick
Dim strResponseTexts As New List(Of String), Codes As New List(Of Long)
Dim t1List, t2List As New List(Of String) ' time before and after get tse data
For rr = firstIndex To lastIndex
Dim r As DataRow = stocksDt(rr)
Dim code As Long
Dim address2 As String = addressMainPage & code.ToString
Dim strFull As String = ""
Dim t1, t2 As String ' time before and after get tse data
t1 = Now.ToString("hh:mm:ss.ff")
t1List.Add(t1)
Try
strFull = Await GetTseData(address2)
Catch ex As Exception
logErrorGetData += ex.ToString
End Try
t2 = Now.ToString("hh:mm:ss.ff")
t2List.Add(t2)
If strFull = String.Empty Then
' some logging operations
Continue For
End If
Codes.Add(Code)
strResponseTexts.Add(strFull)
Next
' saving each pack of data in Db
Dim r2 As Integer = FillDb(dbFile, Codes, strResponseTexts, t1List, t2List)
End Sub
提示:问题与服务器无关。我在 VPS 中同时尝试了相同的程序,它正确下载并保存了 1 分钟时间范围内的所有 url。也许我不知道关于 Async/Await 的一些观点。如何调试我的程序以找到问题?
Edit2:我的 FillDb 方法:
Public Function FillDb(dbFile As String, Codes As List(Of Long), strInputs As List(Of String), Optional t1List As List(Of String) = Nothing, Optional t2list As List(Of String) = Nothing) As Integer
Dim TableNames, SahmValuesList As New List(Of String)
For i = 0 To Codes.Count - 1
Dim code As Long = Codes(i)
Dim strInput As String = strInputs(i)
Dim TableName As String = "s" & code.ToString
Dim strArr() As String = strInput.Split(";")
Array.Copy(strArr, 0, SahmValues, 0, 26)
SahmValues(27) = TimeOfDay.ToString("hh:mm:ss") ' tget field
Dim t1 As String = "" : Dim t2 As String = ""
If t1List IsNot Nothing And i <= t1List.Count - 1 Then t1 = t1List(i)
If t2list IsNot Nothing And i <= t2list.Count - 1 Then t2 = t2list(i)
SahmValues(28) = t1
SahmValues(29) = t2
Names.Add(TableName)
Dim SahmValuesString As String = String.Join(",", SahmValues)
SahmValuesList.Add(SahmValuesString)
Next
AddtoDb_MultiRowsMultiTable(dbFile, stockTableNames.ToArray, siDb_ColumnsName, siDb_ColumnsType, SahmValuesList)
Return 1
End Function
Public Sub AddtoDb_MultiRowsMultiTable(dbFile As String, tableNames As String(), columnNames As String(), columnTypes As String(), values As List(Of String))
If Not System.IO.File.Exists(dbFile) Then SQLiteConnection.CreateFile(dbFile)
Using conn As SQLiteConnection = New SQLiteConnection("Data Source=" & dbFile & ";PRAGMA journal_mode=WAL;")
conn.Open()
Using cmd As SQLiteCommand = conn.CreateCommand()
Using transaction As SQLiteTransaction = conn.BeginTransaction()
For k = 0 To tableNames.Length - 1
Dim tablename As String = tableNames(k)
Dim rowString As String = values(k)
Dim v() As String = rowString.Split(",")
Dim SahmColCreation As String = "(id integer primary key AUTOINCREMENT, "
For i = 0 To columnNames.Length - 1
SahmColCreation += columnNames(i) & " " & columnTypes(i) & ", "
Next
SahmColCreation = SahmColCreation.Remove(SahmColCreation.LastIndexOf(","), 2) + ");"
Dim comString1 As String = String.Format("CREATE TABLE IF NOT EXISTS {0} ", tablename) & SahmColCreation
Dim comString2 As String = ""
If columnNames.Contains("t") Then
Dim index_name As String = "idx_" & tablename
comString2 = String.Format("CREATE INDEX IF NOT EXISTS {0} ON {1} (t);", {index_name, tablename})
End If
Dim SahmRowString As String = "("
For i = 0 To columnNames.Length - 1
SahmRowString += columnNames(i) + ", "
Next
SahmRowString = SahmRowString.Remove(SahmRowString.LastIndexOf(","), 2) + ")"
Dim SahmValues As String = "VALUES ("
For i = 0 To v.Length - 1
Dim val As String = v(i).Trim("'")
If columnTypes(i) = "Integer" Then
SahmValues += val + ", "
Else
SahmValues += "'" + val + "', "
End If
Next
SahmValues = SahmValues.Remove(SahmValues.LastIndexOf(","), 2) + ");"
Dim comString3 As String = String.Format("INSERT INTO {0} ", tablename) & " " & SahmRowString & " " & SahmValues
Dim comStringFull = comString1 & "; " & comString2 & "; " & comString3
cmd.CommandText = comStringFull
cmd.ExecuteNonQuery()
Next
transaction.Commit()
End Using
End Using
End Using
End Sub
解决方案
推荐阅读
- c++ - 我怎样才能让我的碰撞飞机从 obj 文件中拾取超过 1 架飞机
- php - MySQL插入不显示任何内容
- html - 我可以在自定义 HTML 元素中使用标准属性吗?
- vue.js - vuejs 这在我的 eventListner 中是未定义的
- javascript - 如何将字符串值参数传递给 package.json 脚本命令
- android - Android Kotlin Espresso 在单元测试中断言预期活动抛出错误
- azure - 为什么 NLog 到 Azure blob 存储不起作用?
- javascript - 为什么 Brain JS 无论问什么问题总是给出相同的答案?
- c++ - 如何将 SQLite c 文件(合并)与 cpp 应用程序链接?
- javascript - 无法使用 NodeJ 加载样式表或 js 文件