3

I had created a list of threads to achieve Multi Threading that all accepting a single function that returning value. Following is the code that i had tried:

Creation of threads

  Dim txt as String
  For i As Integer = 0 To 15
      txt = ""
      txt = UCase(array.Item(i))
      Dim tempThread As Threading.Thread = New Threading.Thread(AddressOf threadRead)
      tempThread .Start(txt) ' start thread by passing value to it
      Threads.Add(tempThread ) 'Add thread to the list
      'Here i want to add the return value from the thread to RichTextbox
      'as follows
      RichTextBox1.Text = RichTextBox1.Text & vbNewLine & tempThread.ReturnValue
  Next

Function that is addressed by the thread

  Public Function threadRead(ByVal txtInput As String) As String
       Dim stroutput As String = ""
       ' Some operations are performed here
       Return stroutput
  End Function

So the problem is that i can't access the returning value from the called function. can anyone suggest me some method to achieve this?

Thanks in advance

Suji
  • 1,326
  • 1
  • 12
  • 27
  • What version of .net is this for - are you not able to use TPL or Async Await in 4.5 / vs 2012? These would be much simpler. – tom.dietrich Sep 18 '14 at 12:24
  • See [Parameters and Return Values for Multithreaded Procedures](http://msdn.microsoft.com/en-us/library/wkays279.aspx). – spongebob Sep 18 '14 at 12:27
  • VS 2010 with .net FW 4.5 –  Sep 18 '14 at 12:32
  • You are creating 16 threads right away, there is no way to control this that I can see. I'm assuming you are doing this for fun or a school project, there is no reason to even use threading here. If you really want to go down that path, you should use TPL, then you can actually access a return value from a task(thread). – Adam Sep 18 '14 at 13:29
  • 1
    Your example is not *Multi Threading*. You create a thread and then you want to wait until it is finished to get a value. Use a function. Threads are asynchronous. – γηράσκω δ' αεί πολλά διδασκόμε Oct 15 '14 at 13:47
  • I wonder if you aren't taking the example code too literally. The OP knew his code was wrong, so why interpret it as if he thought it were correct as written? It's pretty clear he didn't actually want to block while waiting for each thread, one at a time. – Darryl Oct 20 '14 at 18:10

2 Answers2

8

In my opinion, the easiest way to do this is with a helper object called a BackgroundWorker. You can find the MSDN documentation here.

Here's an example of how to use it:

Private Sub RunFifteenThreads()
   For i As Integer = 1 To 15
      Dim some_data As Integer = i
      Dim worker As New System.ComponentModel.BackgroundWorker
      AddHandler worker.DoWork, AddressOf RunOneThread
      AddHandler worker.RunWorkerCompleted, AddressOf HandleThreadCompletion
      worker.RunWorkerAsync(some_data)
   Next
End Sub

Private Sub RunOneThread(ByVal sender As System.Object, _
                         ByVal e As System.ComponentModel.DoWorkEventArgs)
   Dim stroutput As String = e.Argument.ToString
   ' Do whatever else the thread needs to do here...
   e.Result = stroutput
End Sub

Private Sub HandleThreadCompletion(ByVal sender As Object, _
                                   ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs)
   Dim return_value As String = e.Result.ToString
   RichTextBox1.Text = RichTextBox1.Text & vbNewLine & return_value
End Sub

Each worker object manages its own thread. Calling a worker's RunWorkerAsync method creates a new thread and then raises a DoWork event. The function that handles the DoWork event is executed in the thread created by the worker. When that function completes, the worker raises a RunWorkerCompleted event. The function that handles the RunWorkerCompleted event is executed in the original thread, the one that called RunWorkerAsync.

To pass data between threads, you use the EventArgs parameters (e in the example above) in your event handlers. You can pass a single argument to RunWorkerAsync, which is made available to the new thread via e.Argument. To send data the other direction, from the worker thread to the main thread, you set the value of e.Result in the worker thread, which is then passed to function which handles thread completion, also as e.Result.

You can also send data between threads while the worker thread is still executing, using ReportProgress and ProgressChanged (see MSDN documentation if you're interested).

Darryl
  • 5,907
  • 1
  • 25
  • 36
0

Heres an idea

    Event ValueAcquired(sender As Object, e As ValueAcquiredEventArgs)
    Delegate Sub delValueAcquired(sender As Object, e As ValueAcquiredEventArgs)
    Sub AllocateThread()
        Dim thStart As New System.Threading.ParameterizedThreadStart(AddressOf threadEntry)
        Dim th As New Threading.Thread(thStart)
        th.Start()
    End Sub
    Sub threadEntry()
        threadRead("whatever this is")
    End Sub
    Sub notifyValueAcquired(sender As Object, e As ValueAcquiredEventArgs)
        If Me.InvokeRequired Then
            Me.Invoke(New delValueAcquired(AddressOf notifyValueAcquired), sender, e)
        Else
            RaiseEvent ValueAcquired(sender, e)
        End If
    End Sub
    Public Sub threadRead(ByVal txtInput As String)
        Dim stroutput As String = ""
        ' Some operations are performed here
        'raise your event
        notifyValueAcquired(Me, New ValueAcquiredEventArgs(stroutput))
    End Sub
    Sub me_valueAcquired(sender As Object, e As ValueAcquiredEventArgs) Handles Me.ValueAcquired
        'Use e.Value to access the retrun value of threadRead
    End Sub
    Public Class ValueAcquiredEventArgs
        Public Value As String
        Sub New(value As String)
            Me.Value = value
        End Sub
    End Class
Paul Ishak
  • 1,093
  • 14
  • 19