Link to home
Start Free TrialLog in
Avatar of k3n51mm
k3n51mm

asked on

VB.Net 2005 backgroundWorker

I have a CPU-intensive subroutine that takes a datatable as its parameter. When it begins, the app hangs until it completes. this can take as long as 60 seconds for a 1.5 MB XML file. I can imagine it taking longer to process larger incoming files.

Therefore, I need to show the user something like a progress bar or even just a popup that informs them that the program has not frozen.

What I can't figure out yet is how to execute this subroutine from within the BackgroundWorker_DoWork sub, since its datatable parameter is not declared in the backgroundWorker. I can't just add the datatable parameter, sicne then the signatures don't match. Little help?
Avatar of Fernando Soto
Fernando Soto
Flag of United States of America image

Hi k3n51mm;

When you start the background worker pass the datatable to the background worker DoWork event like so:

BackgroundWorker.RunWorkerAsync(MyDataTable)

then in the DoWork event do something like this

Private Sub BgWorker_DoWork(ByVal sender As Object, _
        ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BgWorker.DoWork

        Dim MyDataTable As DataTable = DirectCast(e.Argument, DataTable)
        ' Now you have access to the data table in the worker thread.

End Sub

Fernando
Avatar of k3n51mm
k3n51mm

ASKER

wow, thanks I will try it and get back to you. Appreciate it!
Not a problem, glad to help. ;=)
Avatar of k3n51mm

ASKER

ok, that didn't work... all I really need to do is make certain that the wait form tells the user what's going on. But right now, the whole thing still freezes for a long time, and calling the routine using multithreading still didn't prevent the issue. Using the following code, the wait form doesn't finish painting before the next instruction has already hung the program:

            frmWait.Show()
            BackgroundWorker1.RunWorkerAsync(tblImpData)
            frmWait.Close()

How can I make sure a small wait form is being shown before I begin the intensive processing?
i tried it with a message box and had the same issue:

            frmWait.Show()                                  <---this doesn't get to finish displaying
            Call GetExistingData(tblImpData)      <---before this hangs the program
            frmWait.Close()

Any other ideas?
Hi k3n51mm;

This code you posted will Show the form frmWait then immediately start the worker thread and then immediately Close the frmWait.

            frmWait.Show()
            BackgroundWorker1.RunWorkerAsync(tblImpData)
            frmWait.Close()

So you may not see the form even displayed in this case.

I will post a complete sample program that does a file search, recursively search directory and sub directories so that you have a complete picture.

Fernando
ASKER CERTIFIED SOLUTION
Avatar of Fernando Soto
Fernando Soto
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
Avatar of k3n51mm

ASKER

That's a lot, I'll have to study it for awhile. Thank you!

I do have another quickie. Since I couldn't really get my head around the thread-safety articles on the Net, I'm using what seems to be a kludge:
Control.CheckForIllegalCrossThreadCalls = False

Is there something I should be doing instead of this? My instinct says yes, but I got rather confused with it. This is my first multithreading experience, sorry.
Hi k3n51mm;

You should never use this statement. It only suppresses the wanning message that the compiles gives.

    Control.CheckForIllegalCrossThreadCalls = False

Because you are using a Background worker thread you can call user interface objects / control from within the ProgressChanged and RunWorkerCompleted event handlers without causing a cross thread violation.

To your question, "Is there something I should be doing instead of this?". The CheckForIllegalCrossThreadCalls is when you attempt to change the state of a GUI control. For example you have a ProgressBar on a form and attempt to update it from within another thread. This is not allowed from another thread. What you need to do to avoid this problem is something like the following.

This method can be called from any thread to modify the GUI.

    ''' PrintErrorMsg:
    ''' Print an error message to the rich text box that displays errors.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub PrintErrorMsg()

        ' Check to see if the TabControl that the RichTextBox is on is in the same thread of execution
        ' as the calling thread. If this is the case the else part of the if state will be executed. If we
        ' are calling this method from another thread then the first part of the if statement is executed
        ' and a request is made from the GUI to call this same method and make the change for the
        ' other thread.
        If tbcOutput.InvokeRequired Then
            Dim pErr As New PrintErrorMessage(AddressOf PrintErrorMsg)
            Me.Invoke(pErr)
        Else
            Dim Msg As String = "******* " & Header & " *******  " & Now().ToLongTimeString() & nl & nl
            Msg &= Line1 & nl
            Msg &= Line2 & nl & nl
            ' Make the Tabpage that holds the error window have focus
            tbcOutput.SelectedTab = tbpErrors
            rtbError.Text = Msg & rtbError.Text
        End If

    End Sub

Fernando