0

我正在尝试制作一些检查 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!"

4

1 回答 1

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 事件中报告。您应该检查那里发生的任何错误。

于 2013-11-11T20:56:05.770 回答