Link to home
Start Free TrialLog in
Avatar of rutledgj
rutledgj

asked on

vb.net How to update UI from task

Ok. So I'm trying to use the task stuff to do parallel programming. I can't figure out how to update a gui label from a task.  

I have Downloads class with method DownloadPatientData(V as Vendor)    Vendor is a class to hold data.

in main form I have:

 While VendorQueue.Count > 0
                Dim v As Vendor = Nothing
                If VendorQueue.TryDequeue(v) = True Then
                    threadCount += 1
                    Console.WriteLine("Processing Org " & v.Org)
                    v.DrFirstVersion = DrFirstVersion
                    Dim d As New Downloads
                    d.ThreadName = "t" & CStr(threadCount)
                    Dim t As Task = Task.Factory.StartNew(Sub() d.DownloadPatientData(v))        
                End If
            End While

So over in the DownloadPatientData method how can I write back to the gui label (lblStatus)?

In regular threading you could add a event handler.  What do you do here?
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Make your Downloads class raise a custom event with the text to display in the label:  
Public Class Downloads

    Public Event Status(ByVal txt As String)

    Private Sub Foo()
        RaiseEvent Status("blah...") ' <-- just an example
    End Sub

End Class

Open in new window


Now, in your form, create a method to receive the event and update the label:  
Public Class Form1

    Private Sub dld_Status(ByVal txt As String)
        If Me.InvokeRequired Then
            Me.Invoke(New Action(Of String)(AddressOf dld_Status), New Object() {txt})
        Else
            Me.lblStatus.Text = txt
        End If
    End Sub

End Class

Open in new window


Finally, use AddHandler() to wire up the event when the instance of Downloads is created:  
...
        Dim d As New Downloads
        d.ThreadName = "t" & CStr(threadCount)
        AddHandler d.Status, AddressOf dld_Status
        Dim t As Task = Task.Factory.StartNew(Sub() d.DownloadPatientData(v))

Open in new window

Avatar of rutledgj
rutledgj

ASKER

Well this compiles but the code never gets to the  Me.lblStatus.Text = txt
It does the Me.Invoke section but nothing else.
The method to recieve the event inthe main form should be:
Public Class Form1

    Private Sub dld_Status(ByVal txt As String)
        If Me.InvokeRequired Then
            Me.Invoke(New Action(Of String)(AddressOf dld_Status), New Object() {txt})
        End If
        Me.lblStatus.Text = txt
    End Sub

End Class

Open in new window

that doesn't work either. Never gets to lblstatus.text = txt
I have also noticed that raising the event from the DownloadPatientData method, even though it doesn't update the label, prevents the application from closing.  It gets stuck in the task.waitall call. Removing the raiseevent allows it to complete as normal.

There must be a different way to update the gui using tasks.

ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is the complete code in the main form.  When the tasks complete I close the app.

 While VendorQueue.Count > 0
                Dim v As Vendor = Nothing

                If VendorQueue.TryDequeue(v) = True Then
                    threadCount += 1
                    Console.WriteLine("Processing Org " & v.Org)
                    v.DrFirstVersion = DrFirstVersion
                    Dim d As New Downloads
                    d.ThreadName = "t" & CStr(threadCount)
                    d.MyVendor = v
                    AddHandler d.ThreadFinished, AddressOf ThreadUpdateHandler
                    '  lstTasks.Add(Task.Factory.StartNew(Sub() d.DownloadPatientData()))
                    Dim t As New Task(Sub() d.DownloadPatientData())
                    t.Start()
                    lstTask.Add(t)
                End If
            End While

            Task.WaitAll(lstTasks.ToArray)

            Application.Exit()





I understand what you are saying. A catch 22.  So what is the alternative?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial