AymAn AbuOmar
AymAn AbuOmar

Reputation: 423

How to use Backgroundworker to load form?

When I try to load a form with a backgroundworker class, it throws an exception because I tried to access an object that was created by another thread, not by the current thread. How to load that form by backgroundworker ?

(I am looking for marquee progress bar while the form is loading)

Upvotes: 4

Views: 8076

Answers (4)

Steven Licht
Steven Licht

Reputation: 770

You cannot do this. Forms have Thread-Affinity. ie. they can ONLY be accessed by the thread that instantiated the Form. You background thread just became the UI thread for the form! So what you MUST do is marshal the call onto the correct thread. Test InvokeRequired. If true, instantiate a delegate, call BeginInvoke and IMMEDIATELY return. Now the call will be marshaled to the correct thread.

Upvotes: 0

Ryszard Dżegan
Ryszard Dżegan

Reputation: 25464

There is no problem to initialize the second form in another thread, but if you want to use it in the context on your main form, you have to use original thread. The follows code creates and initializes new form in background worker and then shows it when initialization is completed in appropriate event handler:

Public Class Form1
Dim form2 As Form2

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

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    form2 = New Form2()
    form2.TextBox1.Text = "Text"
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    form2.Show()
End Sub
End Class

You can use ProgressChanged event of background worker for the purpose of report to progress bar.

Upvotes: 0

fotijr
fotijr

Reputation: 1096

You can't change any controls in the DoWork section of a backgroundworker since it's a separate thread. You'll want to process any data in the DoWork section, then update your form in the RunWorkerCompleted section.

Example:

Private WithEvents bgwTasks As New BackgroundWorker

Private Sub bgwTasks_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwTasks.DoWork
e.Result= GetDatabaseTable()
End Sub

Private Sub bgwTasks_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgwTasks.RunWorkerCompleted
    If e.Result IsNot Nothing Then
        DataGridView1.DataSource = e.Result
    End If
End Sub

Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    If bgwTasks.IsBusy = False Then
        bgwTasks.RunWorkerAsync()
    End If
End Sub

Upvotes: 2

Ruben_PH
Ruben_PH

Reputation: 1824

This will disable checking for Cross Threads

Me.CheckForIllegalCrossThreadCalls = False

I still suggest you search for Cross Thread regarding the proper use of the BackgroundWorker Class.

Upvotes: 0

Related Questions