Link to home
Start Free TrialLog in
Avatar of kanus
kanus

asked on

Invoke Webbrowser from a seperate thread vb.net

Hi all,

I've spent a couple hours trying to figure out threading and how to access form controls from a separate thread but I'm still confused. Any help would be appreciated. Here is some simplified code to give you an example of what I'm trying to do:

    Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick
        Dim newThread As Thread = New Thread(AddressOf Timer2_Work)
        newThread.Start()
    End Sub

    Private Sub Timer2_Work()
                    Dim val As String = "somevalue"
                    Dim element As String = "TheNameOfSomeWebPageElement"
                    WebBrowser1.Document.All(element).InnerText = val
    End Sub

This code gives me the error "Specified cast is not valid." and I have to assume the error is threading related, and the webbrowser control has to be called from the thread its on.

I've tried several things, and tried replicating some examples I've found, but never actually got it working. If you can provide a example of how I could accomplish this, or direct me to a "vb.net threading for complete idiots" page, I would be very grateful.
Avatar of MikeQc
MikeQc
Flag of Canada image

Which line gives you "Specified cast is not valid"?
Avatar of kanus
kanus

ASKER

"WebBrowser1.Document.All(element).InnerText = val"
Trace and check if WebBrowser1.Document.All(element) is not null.
Your document may be not fully loaded and this element may not exists.
Also, is this value is True: WebBrowser1.InvokeRequired
Avatar of kanus

ASKER

Regarding your first question, trying to obtain the value gives me the same "Specified cast is not valid.", I can say for certain the browser was fully loaded.

WebBrowser1.InvokeRequired is True.

Thanks!
Ok, so try this:

Private Sub Timer2_Work()
  If (WebBrowser1.InvokeRequired) Then
    WebBrowser1.BeginInvoke(New MethodInvoker(AddressOf Timer2_Work))
  Else
    Dim val As String = "somevalue"
    Dim element As String = "TheNameOfSomeWebPageElement"
    WebBrowser1.Document.All(element).InnerText = val
  End If
End Sub

Open in new window

Avatar of kanus

ASKER

Thanks MikeQc

I tried it to no avail. It never attempted to execute the following code.
    Dim val As String = "somevalue"
    Dim element As String = "TheNameOfSomeWebPageElement"
    WebBrowser1.Document.All(element).InnerText = val



I guess that only works if the timer is looping?

In the project I'm working on, it only executes the this line of code if certain criteria are met. Once it makes the pass, it won't attempt to make that line of code run again, it will execute a different line of code.

In the project it's like this:
Private Timer2Count As Integer = 0

Private Sub Timer2_Work()
  If Timer2Count = 0 Then
    Do Stuff
  ElseIf Timer2Count = 1
    Dim val As String = "somevalue"
    Dim element As String = "TheNameOfSomeWebPageElement"
    WebBrowser1.Document.All(element).InnerText = val
  End If


Sorry, I was trying to use a really simplistic example of code. Is there a way to run it directly?



Just before the line that crash, add those lines:

        Debug.WriteLine(WebBrowser1.GetType().FullName)
        Debug.WriteLine(WebBrowser1.Document.GetType().FullName)
        Debug.WriteLine(WebBrowser1.Document.All.Count)
        Debug.WriteLine(element)
        Debug.WriteLine(WebBrowser1.Document.All(element).GetType().FullName)
        Debug.WriteLine(WebBrowser1.Document.All(element).InnerText.GetType().FullName)

When it crashes go to the Output window (Debug --> Windows --> Output) and send us what it is written.
We will then see what is that casting problem.
Avatar of kanus

ASKER

When it hits the debug line I get the error:
"Specified cast is not valid."


I know the cause is the thread can't access the webbrowser, I just don't understand how to access the webbrowser from a separate thread.
The first one?!? (WebBrowser1.GetType().FullName)?
Avatar of kanus

ASKER

It stops on this one, but there is nothing in the output window.

Debug.WriteLine(WebBrowser1.Document.GetType().FullName)
Replace the Debug.WriteLine with MsgBox.

You won't be able to copy/paste but you will confirm that at least WebBrowser1 is a System.Windows.Forms.WebBrowser.

After that we will see what is the problem with Document Property.
Avatar of kanus

ASKER

Did as you suggested.

First messagebox showed System.Windows.Forms.WebBrowser and so did the next several hundred messagebox's. When I attempted to debug, it was stuck on:
MsgBox(WebBrowser1.GetType().FullName)
And would not proceed to the next line of code.

Close vb and re-opened the app to ensure it wasn't a fluke. Same result.

Avatar of kanus

ASKER

Then I commented out the first line, like this:
                    'MsgBox(WebBrowser1.GetType().FullName)
                    MsgBox(WebBrowser1.Document.GetType().FullName)
It then gave me the "Specified cast is not valid.". Not sure if you would need to check that line, but figured I would.
several hundred of messagebox's ?!?
What is the delay on Timer2?
Avatar of kanus

ASKER

It doesn't appear the timer was causing it. As I stepped through the application, it stayed on that msgbox step. It didn't attempt to execute any of the before or after it.
But, if you had several hundred messageboxes, that means that the timer event is called a lot of times (and not only one time like you said it should be).

So, what is the delay on your timer?

Also, why are you starting a thread for a so small operation inside a timerElapsed event?
Avatar of kanus

ASKER

"But, if you had several hundred messageboxes, that means that the timer event is called a lot of times (and not only one time like you said it should be)."
I didn't say the timer event was called once, I said that line of code would only execute once. Each time the Timer2_Work() sub is called it increments a number, it will execute the line of code dependent on what number it is on, essentially making it only execute that line of code once, unless the number is reset.  

"So, what is the delay on your timer?"
250

"Also, why are you starting a thread for a so small operation inside a timerElapsed event?"
I have multiple timers in the same application and they are conflicting, cutting each other off in the middle of executing the code, the only way I can prevent the problem is to put them on their own thread.

I feel like I am running in circles here though, why are we chasing the items don't seem to be relevant to the problem? Not trying to come off rude, it's just not making sense to me. I know the answer is a simple one, if you don't know the answer, please allow someone else to answer.
ASKER CERTIFIED SOLUTION
Avatar of MikeQc
MikeQc
Flag of Canada 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 kanus

ASKER

Perfect! Abso freakin lutely perfect!

Thank you! Thank you! Thank you!
Avatar of kanus

ASKER

Thank you.