我正在尝试制作一些可以检查Xbox用户名的内容,但我尝试使用一个落后于它的UI的计时器。所以我想我是用后台工作者做的,但是使用不同的线程,并且调用UI引用并不适合我。有什么帮助吗?
For i As Integer = 0 To ListBox1.Items.Count
Using Wc As New WebClient()
Try
Dim Xbox As String = String.Empty
Xbox = Wc.DownloadString("http://www.xboxgamertag.com/search/" & ListBox1.SelectedItem.ToString())
If Xbox.Contains("Online Status") Then
FlatAlertBox1.Text = "Gamertag " & ListBox1.SelectedItem.ToString & " is taken :("
FlatAlertBox1.kind = FlatAlertBox._Kind.Error
FlatAlertBox1.Visible = True
End If
Catch ex As Exception
FlatAlertBox1.Text = "Gamertag " & ListBox1.SelectedItem.ToString & " is not taken!"
FlatAlertBox1.kind = FlatAlertBox._Kind.Success
FlatAlertBox1.Visible = True
End Try
End Using
Next
ListBox1.SelectedIndex += 1
当我尝试运行它时,我得到:
System.Windows.Forms.dll中发生了'System.InvalidOperationException'类型的异常,但未在用户代码中处理
附加信息:跨线程操作无效:控制从其创建的线程以外的线程访问的“ListBox1”。
如果存在此异常的处理程序,则可以安全地继续该程序。
在线:FlatAlertBox1.Text = "Gamertag " & ListBox1.SelectedItem.ToString & " is not taken!"
答案 0 :(得分:0)
您无法在非UI线程上更新GUI控件,因此您必须在循环期间尝试“报告”调查结果。
这里我只使用ListBox中的字符串副本启动线程:
bgw.RunWorkerAsync(ListBox1.Items.Cast(Of String))
我们需要一个简单的类来报告信息:
Public Class UserStatus
Property Name As String
Property Kind As Integer
End Class
然后在DoWork方法中
Private Sub bgw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bgw.DoWork
For Each s As String In DirectCast(e.Argument, IEnumerable(Of String))
Using Wc As New WebClient()
Dim Xbox As String = String.Empty
Xbox = Wc.DownloadString("http://www.xboxgamertag.com/search/" & s)
If Xbox.Contains("Online Status") Then
bgw.ReportProgress(0, New UserStatus() With {.Name = s, .Kind = Kind.Error})
Else
bgw.ReportProgress(0, New UserStatus() With {.Name = s, .Kind = Kind.Success})
End If
End Using
Next
End Sub
在ProgressChanged事件中,您已阅读状态:
Private Sub bgw_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bgw.ProgressChanged
Dim us As UserStatus = DirectCast(e.UserState, UserStatus)
If us.Kind = Kind.Success Then
FlatAlertBox1.Text = "Gamertag " & us.Name & " is not taken!"
Else
FlatAlertBox1.Text = "Gamertag " & us.Name & " is taken :("
End If
FlatAlertBox1.kind = us.Kind
FlatAlertBox1.Visible = True
End Sub
关于你的代码的一些注意事项。您循环遍历列表但将所有信息放在同一个TextBox中,因此您只能看到列表中的最后一项(除非过程非常慢)。
我删除了Try-Catch。如果BackgroundWorker中发生错误,则会在e.Error属性中的RunWorkerCompleted事件中报告该错误。您应该检查那里发生的任何错误。