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?
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
I had the same problem. As pointed out by Kevin P. Rice, the caller is on a diferente thread than the one the control was created on. A simple solution for this is to use this.Invoke()
everytime the thread needs to interact with a control, therefore, if you desire to have the browser invoke a script, and you wish to call it from inside a separate thread, just do it like this:
this.Invoke(new Action(() => { brw.Document.InvokeScript("jmpend"); }));
Or if you wish to change the property of the browse or another control within the form:
this.Invoke(new Action(() => { button1.Enabled = false; }));
If the declaration of your thread is in another scope than that of your form, and you can't use the this
keyword, you need to find a way to reference the current instance of the form.
I hope this helps. :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.