C# “InvalidCastException” when trying to access webbrowser control from TimerCallback

browserc

Basically I have the same problem as this user:
How to check for TrackBar sliding with mouse hold and release
I fixed this using the first solution provided. However, when the timer is called, I want to call InvokeScript on a webbrowser control. InvokeScript runs without an error, but the javascript function is never called. When I call this script from like a button clicked event handler, the function is called properly.

I found out that when I try to access properties from the webbrowser control (like MessageBox.Show(webBrowser1.DocumentText), this throws a InvalidCastException.

// in constructor:
webBrowser1.AllowWebBrowserDrop = false;
webBrowser1.IsWebBrowserContextMenuEnabled = false;
webBrowser1.WebBrowserShortcutsEnabled = false;
webBrowser1.ObjectForScripting = this;
timer = new System.Threading.Timer(this.TimerElapsed);     

private void trackBar2_ValueChanged(object sender, EventArgs e)
{
        timer.Change(500, -1);
}
private void TimerElapsed(object state)
{
    this.webBrowser1.InvokeScript("jmp_end");
    MessageBox.Show(this.webBrowser1.DocumentText);
    timerRunning = false;
}
private void TimerElapsed(object state)
{
    WebBrowser brw = getBrowser();
    brw.Document.InvokeScript("jmpend");
    MessageBox.Show(brw.DocumentText);
    timerRunning = false;
}

Does anyone know what I am doing wrong here? Or is there another way to get the same result?

After comments about InvokeRequired, this sounds exactly like what I need.. But I can't get it working.. This is what I made from the sample code from C# System.InvalidCastException

public delegate WebBrowser getBrowserHandler();
public WebBrowser getBrowser()
{
    if (InvokeRequired)
    {
        return Invoke(new getBrowserHandler(getBrowser)) as WebBrowser;
    }
    else
    {
        return webBrowser1;
    }
}

private void TimerElapsed(object state)
{
    WebBrowser brw = getBrowser();
    brw.Document.InvokeScript("jmpend");
    MessageBox.Show(brw.DocumentText);
    timerRunning = false;
}

What have I missed here?

Best Answer

The caller (the timer) is on a different thread than the control was created on.

See Control.InvokeRequired Property

Sample code that should address your issue is posted on this question: C# System.InvalidCastException

Related Topic