Mr Dog
Mr Dog

Reputation: 396

Use Tasks/Multi-Thread to load data and show UI

So I am playing with Multi Threading. I have a specific form that takes quiet a while to pop up as it is loading data from file. My idea was to have the data load in the background but still display the form and have a message on the form showing that additional data is loading.

I have everything done, except I am not sure how to get notified the thread is done and is ready to pass me the data as a Dictionary.

This is as far as I have gotten :P

Dim t1 As Task(Of Dictionary(Of String, Double()))

Private Sub cbchannels_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cbchannels.SelectedIndexChanged
    t1 = Task(Of Dictionary(Of String, Double())).Factory.StartNew(Function() Load_Data())
End Sub

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    If t1.IsCompleted Then
        data = t1.Result
    End If
End Sub

I know that the task has the ability to check if its completed and to get the results

 t1.IsCompleted
 t1.Result

Is using a timer to continuously check if the task is completed the only way? And is what I am doing makes sense? I do not want to use a BackgroundWorker.

Upvotes: 1

Views: 838

Answers (2)

jmcilhinney
jmcilhinney

Reputation: 54417

While it's not the only way, the simplest option may be to use a BackgroundWorker. You call RunWorkerAsync to set it off and do the work in the DoWork event handler. When you're done, assign the data to the e.Result property. You can then get that back on the UI thread in the RunWorkerCompleted event handler. E.g.

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

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim table As DataTable = GetData()

    e.Result = table
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    Dim table = DirectCast(e.Result, DataTable)

    'Use table here.
End Sub

Upvotes: 1

usr
usr

Reputation: 171178

That timer is very clever. Fortunately there is a direct was to get notified. You can call ContinueWith on any Task to register a callback that is called when that task completes. This answers your question as asked.

Instead you should be looking into async and await. Running background work in UI apps has gotten a lot easier with C# 5.

Upvotes: 2

Related Questions