线程在结束线程循环之前没有完成任务

时间:2016-08-16 08:13:38

标签: vb.net multithreading api

所以我前段时间做了类似的事情,但这本质上是一个(特定)网站的用户名检查器,他们可以通过文本文件加载用户名,它会把它放到一个列表框中,现在我有了一个开始按钮它意味着检查每个用户名。然而,之前它在检查时冻结了程序,但它确实有效。我试着让它“穿线”,所以它没有冻结。

现在的问题是它没有全部检查,并立即完成。

CODE:

Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
    Button6.Enabled = False
    Dim goodUsers As New SaveFileDialog()
    goodUsers.Filter = "TXT file (*.txt)|*.txt"
    Dim flag As Boolean
    Dim Incomplete As Integer = 0
    Dim Taken As Integer = 0
    Dim sb As New StringBuilder
    If goodUsers.ShowDialog() = DialogResult.OK Then
        Dim checkerMT As New Thread(
            Sub()
                For Each i As String In UsernameList.Items
                    WebRequest.Create("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString)

                    Dim cResult As String = New System.Net.WebClient().DownloadString("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString).ToString

                    If cResult = "taken" Then
                        flag = False
                    ElseIf cResult = "nottaken" Then
                        flag = True
                    End If

                    If flag = True Then
                        sb.Append(i & vbNewLine)
                    Else
                        Incomplete = Incomplete + 1
                        Taken = UsernameList.Items.Count - Incomplete
                    End If
                Next
            End Sub
        )
        checkerMT.Start()
        Try
            File.WriteAllText(goodUsers.FileName, sb.ToString)
        Catch ex As Exception
            Exit Sub
        End Try
    End If
    MessageBox.Show("Checking available usernames, complete!", "NameSniper Pro")
    Button6.Enabled = True
End Sub

2 个答案:

答案 0 :(得分:1)

您无法从UI以外的线程访问UI元素(UsernameList.Items)。而是在表单中添加后台工作程序来处理基本的线程内容(进度报告,完成报告,异常处理)。传入这个对象,其中包含您的工作在不与ui交互的情况下完成工作所需的设置。

Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
    Button6.Enabled = False
    Dim goodUsers As New SaveFileDialog()
    goodUsers.Filter = "TXT file (*.txt)|*.txt"

    If goodUsers.ShowDialog() = DialogResult.OK Then
        'Note: You'll need to add the filenames
        BackgroundWorker1.RunWorkerAsync(New State() With {.Names = {}, .FileName = goodUsers.FileName})
    End If

End Sub

Class State
    Public Names As List(Of String)
    Public StringBuilder As New System.Text.StringBuilder
    Public Incomplete As Integer
    Public Taken As Integer
    Public FileName As String
End Class

Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim state = CType(e.Argument, State)
    For Each i As String In state.Names

        Using cli = New System.Net.WebClient()

            Dim cResult = cli.DownloadString("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString).ToString
            If cResult = "nottaken" Then
                state.StringBuilder.Append(i & vbNewLine)
            Else
                state.Incomplete = state.Incomplete + 1
                state.Taken = state.Names.Count - state.Incomplete
            End If

        End Using
    Next
    IO.File.WriteAllText(state.FileName, state.StringBuilder.ToString)
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    If e.Error IsNot Nothing Then
        MessageBox.Show(e.Error.ToString(), "Error")
    Else
        MessageBox.Show("Checking available usernames, complete!", "NameSniper Pro")
    End If
    Button6.Enabled = True
End Sub

答案 1 :(得分:-1)

  1. SaveFileDialog可以用作“Using directive”

    1. 为什么一方面创建webrequest,另一方面使用webclient?这根本没有意义。

    2. 写下:

    3. ,而不是奇怪的if条件

      flag =(cResult.Equals(“nottaken”))

      1. 您在线程中当前运行的操作之后要运行的所有代码也必须在您的线程中,因为它是异步的。
    4. 如果在线程中使用用户控件,则必须调用 等等..

    5. 请选择Option Strict On和Option Infer Off

      还有很多其他事情你可以做得更好。 请自行删除webrequest和webclient组合,这根本没有意义。

      看看这个,我清了一下:

      Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
      
          Dim Incomplete As Integer = 0
          Dim Taken As Integer = 0
          Dim sb As New StringBuilder
      
          Using goodUsers As SaveFileDialog = new SaveFileDialog()
          goodUsers.Filter = "TXT file (*.txt)|*.txt"
      
          If not goodUsers.ShowDialog() = DialogResult.OK Then Exit Sub
              Dim checkerMT As New Thread(
                  Sub()
      
                  Me.invoke(sub()
             Button6.Enabled = False
                      For Each i As String In UsernameList.Items
                          WebRequest.Create("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString)
      
                          Dim cResult As String = New System.Net.WebClient().DownloadString("http://yatobooter.cf/other/checkusr.php?username=" + i.ToString).ToString
      
                          If (cResult.toLower().Equals("nottaken")) Then
                              sb.Append(String.Concat(i , Environment.NewLine)
                          Else
                              Incomplete += 1
                              Taken = UsernameList.Items.Count - Incomplete
                          End If
      
                      Next
                      File.WriteAllText(goodUsers.FileName, sb.ToString)
                      Button6.Enabled = True
                      MessageBox.Show("Checking available usernames, complete!", "NameSniper Pro")
                  End Sub)
                  End Sub
              )
              checkerMT.IsBackground = True;
              checkerMT.Start()
      
      
      End Sub