我有一个应用程序,每隔几秒检查一次新订单。
如果它在数据库中看到一个新条目,它会触发BackgroundWorker
来处理它。
我的表单上有3个列表框,待处理,已完成并失败。
Theres是第二个BackgroundWorker
进程,在将有问题的项目移动到“已完成”列表框之前,它会异步检查api以查看订单是否已完全处理完毕。
在我在应用程序中一次抛出几个订单之前,一切似乎都工作正常。
它处理订单很好并将它们添加到待处理状态,它将检查其中的一些,但最终会陷入secondbackground工作进程。
它最终会因"This BackgroundWorker is currently busy"
错误而崩溃。
我已经多次查看我的代码了,我无法看到它会崩溃的地方。 对我来说诊断这个的最好方法是什么?
下面是背景工作者的代码,我被卡住了......
Private Sub BuildProgressCheck_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) _
Handles BuildProgressCheck.DoWork
lblstatus.Text = "Checking back on async jobs"
Dim i As Integer
For i = 0 To buildpendinglist.Items.Count - 1
Beep()
Dim cn As New MySqlConnection
cn.ConnectionString = "server=" & dbserver & "; userid=" & dbusername & "; password=" & dbpassword & "; database=" & dbdatabase & ";Convert Zero Datetime=True"
Dim jobcheck As New MySqlDataAdapter("Select * FROM dbcpman_jobs WHERE dbxid='" & buildpendinglist.Items(i) & "'", cn)
Dim jobcheck_table As New DataTable
jobcheck.Fill(jobcheck_table)
Dim jobrow As DataRow
jobrow = jobcheck_table.Select("failed = 'false'").FirstOrDefault()
If Not jobrow Is Nothing Then
Dim job_id As String = jobrow.Item("id")
Dim job_jobid As String = jobrow.Item("jobid")
Dim job_status As String = jobrow.Item("status")
Dim job_dbxid As String = jobrow.Item("dbxid")
Dim jobcommand As String = "command=queryAsyncJobResult&jobId=" & job_jobid
Dim fulljobapicheckurl = cpapiurl & jobcommand
Try
Dim jobapicall As New System.Net.WebClient
jobcheckresult = jobapicall.DownloadString(fulljobapicheckurl)
Catch ex As Exception
''Problem submitting the api request?
End Try
If jobcheckresult.Contains("<jobstatus>1</jobstatus>") Then ''If true, job has completed
Dim doc As New System.Xml.XmlDocument
doc.LoadXml(jobcheckresult) ''api_result contains xml returned from a http request.
If doc.GetElementsByTagName("virtualmachine") IsNot Nothing Then
Dim elem As XmlNodeList = doc.GetElementsByTagName("virtualmachine").Item(0).ChildNodes
For Each item As XmlNode In elem
If item.Name.Equals("state") Then
new_vm_state += ((item.InnerText.ToString()) + Environment.NewLine)
ElseIf item.Name.Equals("hostname") Then
new_vm_hostname += ((item.InnerText.ToString()) + Environment.NewLine)
ElseIf item.Name.Equals("templatename") Then
new_vm_templatename += ((item.InnerText.ToString()) + Environment.NewLine)
ElseIf item.Name.Equals("cpunumber") Then
new_vm_cpunumber += ((item.InnerText.ToString()) + Environment.NewLine)
ElseIf item.Name.Equals("cpuspeed") Then
new_vm_cpuspeed += ((item.InnerText.ToString()) + Environment.NewLine)
ElseIf item.Name.Equals("memory") Then
new_vm_memory += ((item.InnerText.ToString()) + Environment.NewLine)
ElseIf item.Name.Equals("nic") Then
new_vm_netmask += ((item.ChildNodes.Item(3).InnerText.ToString()) + Environment.NewLine)
new_vm_gateway += ((item.ChildNodes.Item(4).InnerText.ToString()) + Environment.NewLine)
new_vm_ipaddress += ((item.ChildNodes.Item(5).InnerText.ToString()) + Environment.NewLine)
new_vm_macaddress += ((item.ChildNodes.Item(11).InnerText.ToString()) + Environment.NewLine)
ElseIf item.Name.Equals("instancename") Then
new_vm_instancename1 += ((item.InnerText.ToString()) + Environment.NewLine)
End If
Next
End If
new_vm_macaddress = new_vm_macaddress.ToUpper
Dim privateip As String = new_vm_ipaddress.Replace(" ", "").ToString
Dim publicip As String = privateip.Replace("172.16.11.", "198.73.112.")
Try
Dim myCommand As New MySqlCommand
Dim myAdapter As New MySqlDataAdapter
Dim SQL As String
myCommand.Connection = cn
cn.Open()
myAdapter.SelectCommand = myCommand
SQL = "DELETE FROM dbcpman_jobs WHERE jobid = '" & job_jobid & "'"
myCommand.CommandText = SQL
myCommand.ExecuteNonQuery()
SQL = "UPDATE dbcpman_vm SET deployresponse = '" & jobcheckresult & "' WHERE dbx_id = '" & job_dbxid & "'"
myCommand.CommandText = SQL
myCommand.ExecuteNonQuery()
SQL = "UPDATE dbcpman_vm SET macaddress = '" & new_vm_macaddress & "' WHERE dbx_id = '" & job_dbxid & "'"
myCommand.CommandText = SQL
myCommand.ExecuteNonQuery()
SQL = "UPDATE dbcpman_vm SET publicip = '" & publicip & "' WHERE dbx_id = '" & job_dbxid & "'"
myCommand.CommandText = SQL
myCommand.ExecuteNonQuery()
SQL = "UPDATE dbcpman_vm SET privateip = '" & privateip & "' WHERE dbx_id = '" & job_dbxid & "'"
myCommand.CommandText = SQL
myCommand.ExecuteNonQuery()
cn.Close()
Dim new_vm_username As String = "clouduser"
Dim new_vm_password As String = GeneratePassword(7)
System.Threading.Thread.Sleep(1000)
Dim new_vm_support_username As String = "dbxsupport"
Dim new_vm_support_password As String = GenerateSupportPassword(7)
cn.Open()
myAdapter.SelectCommand = myCommand
SQL = "INSERT into dbcpman_credentials(username1, username2, password1, password2, type, link) VALUES ('" & new_vm_username & "','" & new_vm_support_username & "','" & new_vm_password & "','" & new_vm_support_password & "','Server root logon','" & job_dbxid & "')"
myCommand.CommandText = SQL
myCommand.ExecuteNonQuery()
SQL = "INSERT into dbcpman_vm_boot(dbxid, ip, macaddress, hostname) VALUES ('" & job_dbxid & "','" & new_vm_ipaddress & "','" & new_vm_macaddress & "','" & job_dbxid & "')"
myCommand.CommandText = SQL
myCommand.ExecuteNonQuery()
cn.Close()
Try ''''add monitoring for this new host
Dim monitorurl As String = "http://192.168.16.32/addhost.php?hostname=" & job_dbxid & "&ipaddr=" & publicip
Dim webClient As New System.Net.WebClient
Dim monresult As String = webClient.DownloadString(monitorurl)
If monresult = "SUCCESS" Then
''success message
Else
''fail message
End If
Catch ex As Exception
End Try
buildcompletedlist.Items.Add(buildpendinglist.Items(i))
buildpendinglist.Items.Remove(buildpendinglist.Items(i))
buildprogresscheckactive = 0
BuildProgressCheck.CancelAsync()
Catch ex As Exception
End Try
ElseIf jobcheckresult.Contains("<jobstatus>0</jobstatus>") Then ''If true, job is still pending
''job still pending - do nothing, will check again on next pass
ElseIf jobcheckresult.Contains("<jobstatus>2</jobstatus>") Then ''If true, job has failed
Try
Dim myCommand As New MySqlCommand
Dim myAdapter As New MySqlDataAdapter
Dim SQL As String
myCommand.Connection = cn
cn.Open()
myAdapter.SelectCommand = myCommand
SQL = "UPDATE dbcpman_jobs SET failed = 'true' WHERE jobid = '" & job_jobid & "'"
myCommand.CommandText = SQL
myCommand.ExecuteNonQuery()
cn.Close()
buildfailedlist.Items.Add(buildpendinglist.Items(i))
buildpendinglist.Items.Remove(buildpendinglist.Items(i))
Catch ex As Exception
BuildProgressCheck.CancelAsync()
buildprogresscheckactive = 0
End Try
End If
End If
Next
buildprogresscheckactive = 0
End Sub
答案 0 :(得分:0)
基于附加文本和代码的最佳猜测如下:
"..checks every few seconds for new orders."
"This BackgroundWorker is currently busy"
因此,我相信您在Tick
的{{1}}事件中开始异步工作。所以,让我们说你的计时器每2秒钟滴答一次。
Timer
现在,让我们假设在Friend WithEvents mytimer As New System.Windows.Forms.Timer With {.Interval = 2000, .Enabled = True}
Private Sub _Tick(sender As Object, e As EventArgs) Handles mytimer.tick
Me.BuildProgressCheck.RunWorkerAsync()
End Sub
中执行6个刻度BuildProgressCheck_DoWork
。没有错误发生,一切似乎都没问题。但是,在第7个刻度,它需要less than 2 seconds
。然后,当计时器第8次加注时,3 seconds
为BackGroundWorker
并抛出错误。
您需要做的是在运行worker之前暂停计时器,并在worker完成后恢复它。这是一个例子:
"currently busy"