Jonno
Jonno

Reputation: 307

VB Net - Pass data from Thread to Main GUI

I've managed to get the data I want in a thread, however I'm having trouble getting my head around passing the data back into my main thread (GUI).

I'm grabbing data from a network stream in a thread, then need to pass it to my main thread in order to pass to other classes etc.

I've seen it mentioned to use backgroundworker for this, but as I'm expecting it to gather data periodically and never stop, I thought a separate thread for this would be best, but I'm very new to multithreading.

If threading is the correct way to go, how can I pass data from it back to my main thread in order to use this for other stuff? I've seen delegates and events mentioned a lot but can't see how I'd pass data with these?

Thanks

Upvotes: 3

Views: 2455

Answers (1)

Victor Zakharov
Victor Zakharov

Reputation: 26464

Please study this example, and let me know if it fits your requirements:

enter image description here

Controls required: lstItems (ListBox), btnStart (Button), btnStop (Button), Timer1 (Timer).

Form1 code:

Public Class Form1
  Dim p_oStringProducer As StringProducer

  Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
    p_oStringProducer = New StringProducer
    p_oStringProducer.Start()
    Timer1.Enabled = True
  End Sub

  Private Sub btnStop_Click(sender As Object, e As EventArgs) _ 
                                                          Handles btnStop.Click
    Timer1.Enabled = False
    p_oStringProducer.Stop()
  End Sub

  Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim asQueue As Concurrent.ConcurrentQueue(Of String) =
      p_oStringProducer.MessageQueue
    While asQueue.Count > 0
      Dim sItem As String = Nothing
      asQueue.TryDequeue(sItem)
      lstItems.Items.Add(sItem)
    End While
  End Sub
End Class

StringProducer code:

Imports System.Threading.Tasks

Public Class StringProducer
  Private p_fKeepRunning As Boolean
  Private p_oTask As task
  Private p_aMessageQueue As Concurrent.ConcurrentQueue(Of String)
  Private p_iNextMessageId As Integer

  Public ReadOnly Property MessageQueue As _
                             Concurrent.ConcurrentQueue(Of String)
    Get
      Return p_aMessageQueue
    End Get
  End Property

  Sub New()
    p_oTask = New Task(AddressOf TaskBody)
    p_aMessageQueue = New Concurrent.ConcurrentQueue(Of String)
    p_iNextMessageId = 0
  End Sub

  Public Sub Start()
    p_fKeepRunning = True
    p_oTask.Start()
  End Sub

  Public Sub [Stop]()
    p_fKeepRunning = False
  End Sub

  Private Sub TaskBody()
    While p_fKeepRunning
      Threading.Thread.Sleep(2000)
      p_aMessageQueue.Enqueue("Message #" & p_iNextMessageId)
      p_iNextMessageId += 1
    End While
  End Sub

  Protected Overrides Sub Finalize()
    MyBase.Finalize()
    Me.Stop()
  End Sub
End Class

This was not extensively tested, but it should give you a head start.

Upvotes: 6

Related Questions