I'm trying to make something that checks Xbox Usernames, but I tried to do so with a timer, which lags the UI of it. So I figured I do it with a background worker, but with the different threads, and calling UI references isn't really working out for me. Any help?
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
When I try to run it, I get:
An exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll but was not handled in user code
Additional information: Cross-thread operation not valid: Control 'ListBox1' accessed from a thread other than the thread it was created on.
If there is a handler for this exception, the program may be safely continued.
On the line : FlatAlertBox1.Text = "Gamertag " & ListBox1.SelectedItem.ToString & " is not taken!"
You can't update GUI controls on a non-UI thread, so you will have to try "reporting" the findings during your loop.
Here I just start the thread with a copy of strings from the ListBox:
bgw.RunWorkerAsync(ListBox1.Items.Cast(Of String))
We need a simple class to report information:
Public Class UserStatus
Property Name As String
Property Kind As Integer
End Class
Then in the DoWork method
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
In the ProgressChanged event, you read your status:
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
A couple of notes about your code though. You are looping through a list but placing all your information in the same TextBox, so you are only ever seeing the last item in the list (unless the process is really slow).
I removed the Try-Catch. If an error occurs in a BackgroundWorker, it will get reported in the RunWorkerCompleted event in the e.Error property. You should examine any errors that occurred there.