2012-01-28 54 views
3

基本上我有这个用户相同的问题: How to check for TrackBar sliding with mouse hold and release 我使用提供的第一个解决方案解决了这个问题。但是,当定时器被调用时,我想在Web浏览器控件上调用InvokeScript。 InvokeScript运行时没有错误,但JavaScript函数从不被调用。当我从像点击按钮的事件处理程序调用此脚本时,函数被正确调用。C#“InvalidCastException”当试图从TimerCallback访问webbrowser控制

我发现,当我尝试访问属性从WebBrowser控件(如MessageBox.Show(webBrowser1.DocumentText),这将引发一个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; 
} 

有谁知道我在做什么错在这里?还是有另一种方式来获得相同的结果?

在关于InvokeRequired的评论后,这听起来完全像我需要..但我无法得到它的工作..这是我从示例代码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; 
} 

我在这里错过了什么?

+1

请张贴您的代码。 – ChrisF 2012-01-28 21:46:07

+0

请参阅:http://stackoverflow.com/questions/5268281/c-sharp-system-invalidcastexception – 2012-01-28 22:06:24

+1

使用System.Windows.Forms.Timer来避免挑战IE以线程安全的方式提供属性。 – 2012-01-28 22:31:39

回答

2

我有同样的问题。正如Kevin P. Rice指出的那样,调用者处于一个不同于创建控件的线程上。一个简单的解决方案是每次线程需要与控件进行交互时使用this.Invoke(),因此,如果您希望让浏览器调用脚本,并且希望从单独的线程内部调用它,则可以这样做:

this.Invoke(new Action(() => { brw.Document.InvokeScript("jmpend"); })); 

或者,如果你想改变表格内浏览的财产或其他控件:

this.Invoke(new Action(() => { button1.Enabled = false; })); 

如果你的线程的声明是在另一个范围上比你的表格,你不能使用关键字this,您需要找到一种方法来引用表单的当前实例。

我希望这会有所帮助。 :)

+0

我刚刚意识到这篇文章是从4年前开始的...... – 2016-01-11 04:02:51