【问题标题】:C# "InvalidCastException" when trying to access webbrowser control from TimerCallback尝试从 TimerCallback 访问 webbrowser 控件时的 C#“InvalidCastException”
【发布时间】:2012-01-28 21:45:11
【问题描述】:

基本上我和这个用户有同样的问题: How to check for TrackBar sliding with mouse hold and release 我使用提供的第一个解决方案解决了这个问题。但是,当调用计时器时,我想在 webbrowser 控件上调用 InvokeScript。 InvokeScript 运行时没有错误,但从不调用 javascript 函数。当我从按钮单击事件处理程序中调用此脚本时,该函数被正确调用。

我发现当我尝试从 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 的 cmets 之后,这听起来完全符合我的需要.. 但我无法让它工作.. 这是我从 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;
}

我在这里错过了什么?

【问题讨论】:

  • 使用 System.Windows.Forms.Timer 避免挑战 IE 以线程安全的方式提供属性。
  • 我添加了一些代码来澄清我的问题。我很抱歉不清楚。希望有人看到我所缺少的。提前致谢。
  • 您是否将 Timer 放置在 Visual Studio 设计器中的 windows 窗体上?请仔细阅读此处的“备注”:msdn.microsoft.com/en-us/library/…——此外,您正在停止事件处理程序中的计时器。您可能希望在计时器设置中改用 AutoReset = false
  • 不,它是一个 System.Threading.Timer,它没有 AutoReset 属性。而 timerRunning 是一个布尔值,在技术上与 Timer 本身无关。

标签: c# browser


【解决方案1】:

调用者(计时器)与创建控件的线程不同。

Control.InvokeRequired Property

应该解决您的问题的示例代码发布在此问题上:C# System.InvalidCastException

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。正如 Kevin P. Rice 所指出的,调用者位于与创建控件的线程不同的线程上。一个简单的解决方案是在每次线程需要与控件交互时使用this.Invoke(),因此,如果您希望浏览器调用脚本,并且希望从单独的线程中调用它,只需这样做这个:

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

    或者,如果您希望更改浏览或表单中其他控件的属性:

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

    如果你的线程声明在你的表单之外的另一个范围内,并且你不能使用this关键字,你需要找到一种方法来引用表单的当前实例。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多