Request help with backgroundworker

J. Scott Elblein

Well-known member
Joined
Dec 14, 2006
Messages
166
Location
Chicago
Programming Experience
10+
I am learning my way around the BGW now, and and getting an "InvalidCastException was unhandled by user code" error on this line of code when being sent through the BGW thread ("Specified cast is not valid."):

VB.NET:
strTotalPages = wbr.DocumentText.Substring(wbr.DocumentText.IndexOf("pagingOf"))

I'm thinking it has to do with the fact that I have "wbr as webbrowser" as a parameter in the call to the Sub, and it's outside of the BGW thread now? If so, how would I go about fixing this?

Also, I would love some information on changing things IN a Sub in a BGW thread. I have read so far that all things having to do w/the UI must be done with bgw_runworkercompleted, but a couple things I'm trying to change at the time of it running are in areas that I can't really wait until it's completed to do, (some label changes and a progressbar)

TIA
 
There shouldn't be any casting issues with that expression, your "str" variable is a String, right?

Use the wbr Progress event which is also UI safe, (you also have to instruct it to report progress), you can put anything in the state parameter.
 
Yes sir, I have the string declaerd as a string. to be exact, here is how it is declared, just before the line where the error happens:

VB.NET:
Static Dim strTotalPages As String = String.Empty

So even though I am passing the webbrowser object that is on my UI as a parameter in the BGW thread, it would not cause the error?
 
You are passing what where?
 
lol

I am calling this sub in the bgw_dowork event:

VB.NET:
Public Sub Collect(ByVal wbr As WebBrowser, ByVal intResetList As Integer)

The above sub is in a module. I have the webbrowser on frmMain named wbrBrowser, and in DoWork I'm calling it like:

Collect(wbrBrowser,1)

I was just wondering if the fact that the browser is on the form, and then the BGW is in it's own thread. Kinda like trying to update a progressbar on the form from within a bgw thread? This bgw stuff is kinda confusing so far, lol.
 
Dowork isn't UI safe. Can't you just pass the doc text in the state parameter when you start the work?
 
The BackgroundWorker is very NOT confusing, which is the whole point. Firstly, it's important to get the terminology right. A BackgroundWorker is not ON any thread. All objects are accessible from all threads all the time. Any object can execute a method on any particular thread. It is most correct to say that a method is executing on or in a thread, not that any particular object is on a thread.

Further, even controls are accessible from any thread. The problem is that any method that accesses a control's handle must be executing on the same thread that created that handle in the first place or you're in trouble. To say that the members of a control are not thread-safe is to say that it is not safe to access those members on any thread other than the one that created the control's handle.

Control's can be created on any thread, so when we say "the UI thread" that is not completely correct, but it is usually a bad idea to create controls on any thread other than the main thread of the process. That's not always the case though. For instance, when the VB application framework creates a splash screen it does so on a worker thread.

Now, here's the whole point of the BackgroundWorker:

1. You call RunWorkerAsync from the main thread, pass an Object parameter if desired.

2. The DoWork event is raised in a background thread automatically, thus your DoWork event handler is executed in a background thread without you having to explicitly create a Thread object.

3. If you passed a parameter to the RunWorkerAsync method then you can retrieve it from the e.Argument property in the DoWork event handler. This allows you to pass any data needed by the background thread directly in without using member variables.

4. If desired you call the ReportProgress method, passing an Integer from 0 to 100 to indicate the current progress percentage and, optionally, another Object.

5. Calling the ReportProgress method raises the ProgressChanged event in the main thread, thus your ProgressChanged event handler is executed on the main thread. This allows you to access any controls you like without having to explicitly delegate. If you passed a second parameter to the ReportProgress method you can retrieve it from the e.UserState property in the ProgressChanged event handler. This allows you to pass any data at all back out to the UI any time you want.

6. When the DoWork event handler completes you can save an Object in the e.Result property.

7. When the background thread has completed the RunWorkerCompleted event is raised in main thread, thus your RunWorkerCompleted event handler is executed in the main thread. This means that you can update the UI when the job is done. If you assigned a value to the e.Result property in the DoWork event handler you can get that data back from the e.Result property in the RunWorkerCompleted event handler. This allows you to pass data back out to the UI when you're done.

See? Very simple: RunWorkerAsync, DoWork, ReportProgress, ProgressChanged, RunWorkerCompleted.
 
Back
Top