Многопоточность Функция в VB.Net - PullRequest
0 голосов
/ 22 декабря 2010

Я пытаюсь использовать многопоточное приложение так, чтобы оно было видно во время выполнения процесса, вот что у меня есть:

Private Sub SendPOST(ByVal URL As String)
    Try
        Dim DataBytes As Byte() = Encoding.ASCII.GetBytes("")
        Dim Request As HttpWebRequest = TryCast(WebRequest.Create(URL.Trim & "/webdav/"), HttpWebRequest)
        Request.Method = "POST"
        Request.ContentType = "application/x-www-form-urlencoded"
        Request.ContentLength = DataBytes.Length
        Request.Timeout = 1000
        Request.ReadWriteTimeout = 1000

        Dim PostData As Stream = Request.GetRequestStream()
        PostData.Write(DataBytes, 0, DataBytes.Length)

        Dim Response As WebResponse = Request.GetResponse()
        Dim ResponseStream As Stream = Response.GetResponseStream()
        Dim StreamReader As New IO.StreamReader(ResponseStream)
        Dim Text As String = StreamReader.ReadToEnd()
        PostData.Close()
    Catch ex As Exception
        If ex.ToString.Contains("401") Then
            TextBox2.Text = TextBox2.Text & URL & "/webdav/" & vbNewLine
        End If
    End Try
End Sub

Public Sub G0()
    Dim siteSplit() As String = TextBox1.Text.Split(vbNewLine)

    For i = 0 To siteSplit.Count - 1
        Try
            If siteSplit(i).Contains("http://") Then
                SendPOST(siteSplit(i).Trim)
            Else
                SendPOST("http://" & siteSplit(i).Trim)
            End If
        Catch ex As Exception
        End Try
    Next
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim t As Thread
    t = New Thread(AddressOf Me.G0)
    t.Start()
End Sub

Однако, субкод 'G0' невыполняется вообще, и мне нужно многопоточность 'SendPOST', поскольку это замедляет работу приложения.

Ответы [ 5 ]

3 голосов
/ 22 декабря 2010
    Catch ex As Exception
    End Try

Очень эффективный способ не дать .NET сказать вам, что вы сделали не так. Не зная, почему это не работает, это неизбежный результат.

Удалить это.

1 голос
/ 22 декабря 2010

Вы должны обернуть метод, который обращается к компоненту пользовательского интерфейса в делегате (он не должен быть именованным делегатом; он может быть анонимным или Action или Func), а затем передать его Me.Invoke, на что ссылались другие.

В этом примере я упаковываю функцию разделения в лямбду и назначаю эту лямбду переменной типа Func(Of String()). Затем я передаю эту переменную в Me.Invoke.

Public Sub G0()        
    Dim siteSplitFunc As Func(Of String()) = Function() _
                             TextBox1.Text.Split(vbNewLine.ToCharArray())
    Dim siteSplit As String() = CType(Me.Invoke(siteSplitFunc), String())

    For i = 0 To siteSplit.Count - 1
        Try
            If siteSplit(i).Contains("http://") Then
                SendPOST(siteSplit(i).Trim)
            Else
                SendPOST("http://" & siteSplit(i).Trim)
            End If
        Catch ex As Exception
            'Do something useful
        End Try
    Next
End Sub
1 голос
/ 22 декабря 2010
Public Class Form1
    'This just shows some concepts of threading.
    'it isn't intended to do anything
    'requires a Button, and two Labels
    '
    Private Sub Button1_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                          Handles Button1.Click

        'starts / stops a test thread
        'isRun = 0 no thread running, start one
        'isRun = 1 thread running, stop it

        If Threading.Interlocked.Read(isRun) = 0L Then
            'start thread
            Threading.Interlocked.Increment(isRun)
            t = New Threading.Thread(AddressOf showTime)
            'simple threading app - display time about twice per second
            t.IsBackground = True 'from a background thread
            t.Start()
        Else
            'stop thread
            Threading.Interlocked.Exchange(isRun, 0L)
            t.Join() 'wait for thread to end
            Threading.Monitor.Enter(listLock)
            intervalList.Clear() 'clear the list
            Threading.Monitor.Exit(listLock)
            Label1.Text = "Stop"
            Label2.Text = ""
        End If
    End Sub

    Dim t As Threading.Thread
    Dim intervalList As New List(Of Double)
    Dim listLock As New Object
    Dim isRun As Long = 0L

    Private Sub showTime()
        Dim dlgt As New UpdLblDel(AddressOf UpdateLabel) 'delegate for UI access
        Dim lastDateTime As DateTime = Nothing

        Do
            Dim d As DateTime = DateTime.Now
            If lastDateTime <> Nothing Then
                'record difference of times - check sleep interval
                Threading.Monitor.Enter(listLock)
                intervalList.Add((d - lastDateTime).TotalMilliseconds)
                Threading.Monitor.Exit(listLock)
            End If
            lastDateTime = DateTime.Now
            dlgt.BeginInvoke(d, Nothing, Nothing) 'update the UI - note immediate return
            Threading.Thread.Sleep(500) 'sleep for approx. 500 ms.
        Loop While Threading.Interlocked.Read(isRun) = 1L
    End Sub

    Delegate Sub UpdLblDel(ByVal theTime As Object)

    Private Sub UpdateLabel(ByVal theTime As Object)
        If Threading.Interlocked.Read(isRun) = 1L Then
            If Label1.InvokeRequired Then 'prevent cross-thread errors
                Label1.BeginInvoke(New UpdLblDel(AddressOf UpdateLabel), theTime)
                Exit Sub
            Else
                Label1.Text = CType(theTime, DateTime).ToString("HH:mm:ss.f") 'show the time from the background thread
            End If
            If Threading.Interlocked.Read(intervalList.Count) >= 10L Then
                'take average
                Threading.Monitor.Enter(listLock)
                Dim avg As Double = intervalList.Sum / intervalList.Count 'sum all of the intervals / count
                intervalList.Clear() 'clear the list
                intervalList.Add(avg) 'forward the average
                Label2.Text = avg.ToString("n2") 'show average
                Threading.Monitor.Exit(listLock)
            End If
        End If
    End Sub
End Class
0 голосов
/ 22 декабря 2010

Вот делегат и соответствующий метод.Вы вызываете метод для обновления текстового поля, и он выясняет, должен ли он проксифицировать метод для вас, в основном спрашивая форму, находится ли он в том же потоке:

Private Delegate Sub UpdateTextBoxDelegate(ByVal text As String)
Private Sub UpdateTextBox(ByVal text As String)
    If Me.InvokeRequired Then
        Me.Invoke(New UpdateTextBoxDelegate(AddressOf UpdateTextBox), text)
    Else
        TextBox2.Text &= text
    End If
End Sub

Чтобы использовать его, просто измените оператор catch на:

        If ex.ToString.Contains("401") Then
            UpdateTextBox(URL & "/webdav/" & vbNewLine)
        End If
0 голосов
/ 22 декабря 2010

Вы не можете получить доступ к объекту пользовательского интерфейса напрямую из потока.

Когда вы хотите прочитать / написать текстовое поле, вы должны сделать это в потоке пользовательского интерфейса. Это можно сделать с помощью Invoke. Или, что еще лучше, отправляйте / получайте информацию с параметрами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...