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?
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?
ASKER
wow, thanks I will try it and get back to you. Appreciate it!
Not a problem, glad to help. ;=)
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.RunWorke rAsync(tbl ImpData)
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?
frmWait.Show()
BackgroundWorker1.RunWorke
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
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.RunWorke rAsync(tbl ImpData)
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
This code you posted will Show the form frmWait then immediately start the worker thread and then immediately Close the frmWait.
frmWait.Show()
BackgroundWorker1.RunWorke
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.CheckForIllegalCro ssThreadCa lls = 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.
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.CheckForIllegalCro
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.CheckForIllegalCro ssThreadCa lls = 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 CheckForIllegalCrossThread Calls 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(AddressO f 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
You should never use this statement. It only suppresses the wanning message that the compiles gives.
Control.CheckForIllegalCro
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 CheckForIllegalCrossThread
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(AddressO
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
When you start the background worker pass the datatable to the background worker DoWork event like so:
BackgroundWorker.RunWorker
then in the DoWork event do something like this
Private Sub BgWorker_DoWork(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWo
Dim MyDataTable As DataTable = DirectCast(e.Argument, DataTable)
' Now you have access to the data table in the worker thread.
End Sub
Fernando