user3412559
user3412559

Reputation: 31

VB.net multithreading for loop, parallel threads

I have a simple form with 2 RichTextBoxes and 1 button, the code grabs the url address from RichTextBox1 and phrases the page for the title field using regex and appends it to RichTextBox2. I want to multithread everything in such way that none of the url's are skipped and the thread numbers can be set ( according to the system free resources ) For example, let's say 10 threads to run in parallel. I searched everything and the best that I managed to do is run everything in a background worker and keep the GUI from freezing while working. A short code sample will be of much help, I am a beginner in VB.net.

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        For i = 0 To RichTextBox1.Lines.Length - 1
            If RichTextBox1.Lines(i).Contains("http://") Then
                Dim html As String = New System.Net.WebClient() _
                    .DownloadString(RichTextBox1.Lines(i))
                Dim pattern As String = "(?<=\<title\>)([^<]+?)(?=\</title\>)"
                Dim match As System.Text.RegularExpressions.Match = _
                    System.Text.RegularExpressions.Regex.Match(html, pattern)
                Dim title As String = match.Value
                RichTextBox2.AppendText(title & vbCrLf)
            End If
        Next
    End Sub
End Class

Updated code ( throwing "Index was outside the bounds of the array." errors. )

    Imports System
Imports System.Threading

Public Class Form1
    Public Sub test(ByVal val1 As String, ByVal val2 As String)
        Dim zrow As String
        zrow = RichTextBox1.Lines(val1)

        If zrow.Contains("http://") Then
            Dim html As String = New System.Net.WebClient().DownloadString(zrow)
            Dim pattern As String = "(?<=\<title\>)([^<]+?)(?=\</title\>)"
            Dim match As System.Text.RegularExpressions.Match = System.Text.RegularExpressions.Regex.Match(html, pattern)
            Dim title As String = match.Value
            RichTextBox2.AppendText(val2 & title & vbCrLf)
        End If
    End Sub

    Public Sub lastfor(ByVal number)
        Dim start As Integer = number - 100

        For x = start To number - 1
            Try
                test(x, x)
                RichTextBox2.AppendText(x & RichTextBox1.Lines(x).Trim & vbCrLf)
            Catch ex As Exception
                'MsgBox(ex.Message)
                RichTextBox3.AppendText(ex.Message & vbCrLf & vbCrLf)
            End Try
        Next

    End Sub
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Control.CheckForIllegalCrossThreadCalls = False
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim TotalLines As String = RichTextBox1.Lines.Length - 1
        Dim TotalThreads As Integer = 10
        Dim LinesPerThread As Integer = TotalLines / TotalThreads
        Dim increment As String = LinesPerThread

        Dim zdata(TotalThreads) As String
        For i = 0 To TotalThreads - 1
            zdata(i) = increment
            increment = increment + LinesPerThread
        Next





        Dim lst As New List(Of Threading.Thread)
        For Each bump As String In zdata
            Dim t As New Threading.Thread(Function(l As String)
                                              'Do something with l
                                              'Update GUI like this:
                                              If bump = String.Empty Or bump Is Nothing Then
                                              Else

                                                  lastfor(l)
                                                  'MsgBox(l)
                                              End If
                                          End Function)
            lst.Add(t)
            t.Start(bump)
        Next



        'test(1)
    End Sub
End Class

Upvotes: 3

Views: 10970

Answers (1)

Shreyas Kapur
Shreyas Kapur

Reputation: 679

There are two ways two achieve this:

First, if you are using .NET 4.0, you could use a Parallel.ForEach loop:

        Parallel.ForEach(RichTextBox1.Lines, Function(line As String)
                                             ' Do something here
                                             ' To update the GUI use:
                                             Me.Invoke(Sub()
                                                           ' Update GUI like this...
                                                       End Sub)
                                             Return Nothing
                                         End Function)

The other way is to do this manually (and you will have slightly more control):

Dim lst As New List(Of Threading.Thread)
    For Each line In RichTextBox1.Lines
        Dim t As New Threading.Thread(Function(l As String)
                                          'Do something with l
                                          'Update GUI like this:
                                          Me.Invoke(Sub()
                                                        'Update Gui...
                                                    End Sub)
                                      End Function)
        lst.Add(t)
        t.Start(line)
    Next

Both of these are very crude, but will get the job done.

EDIT:

Here is a sample code that will control the number of threads:

Dim lst As New List(Of Threading.Thread)
    Dim n As Integer = 1 ' Number of threads.
    Dim npl As Integer = RichTextBox1.Lines / n
    Dim seg As New List(Of String)
    For Each line In RichTextBox1.Lines
        For i = npl - n To npl
            seg.Add(RichTextBox1.Lines.Item(i))
        Next
        Dim t As New Threading.Thread(Function(l As String())
                                          For Each lin In l
                                              ' TO-DO...
                                          Next
                                          'Do something with l
                                          'Update GUI like this:
                                          Me.Invoke(Sub()
                                                        'Update Gui...
                                                    End Sub)
                                      End Function)
        lst.Add(t)
        t.Start(seg.ToArray())
    Next

*The above code might have bugs.

Upvotes: 1

Related Questions