C # «InvalidCastException» при попытке получить доступ к элементу управления веб-браузера из TimerCallback - PullRequest
3 голосов
/ 29 января 2012

В основном у меня та же проблема, что и у этого пользователя: Как проверить скольжение TrackBar при удержании и отпускании мыши Я исправил это, используя первое предоставленное решение. Тем не менее, когда вызывается таймер, я хочу вызвать InvokeScript для элемента управления веб-браузера. InvokeScript работает без ошибок, но функция javascript никогда не вызывается. Когда я вызываю этот скрипт из обработчика событий, подобного нажатой кнопке, функция вызывается правильно.

Я обнаружил, что при попытке доступа к свойствам из элемента управления веб-браузера (например, 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;
}

Что я здесь пропустил?

Ответы [ 2 ]

6 голосов
/ 29 января 2012

Вызывающий (таймер) находится в потоке, отличном от того, в котором был создан элемент управления.

См. Свойство Control.InvokeRequired

Пример кода, который должен адресовать вашпо этому вопросу опубликована проблема: C # System.InvalidCastException

2 голосов
/ 11 января 2016

У меня была такая же проблема.Как указал Кевин П. Райс, вызывающая сторона находится на другом потоке, чем тот, на котором был создан элемент управления.Простым решением для этого является использование this.Invoke() каждый раз, когда поток должен взаимодействовать с элементом управления, поэтому, если вы хотите, чтобы браузер вызывал скрипт, и вы хотите вызывать его из отдельного потока, просто сделайте это какthis:

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

Или, если вы хотите изменить свойство просмотра или другой элемент управления в форме:

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

Если объявление вашего потока находится в другой области видимости, чем этовашей формы, и вы не можете использовать ключевое слово this, вам нужно найти способ ссылки на текущий экземпляр формы.

Надеюсь, это поможет.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...