InvalidCastException с WebBrowser.IsBusy или ReadyState (VB .NET) - PullRequest
3 голосов
/ 16 декабря 2009

Я играл с методом, предложенным в качестве ответа на другой мой вопрос ( Автоматизировать вход на сайт и заполнять форму? ), и заметил кое-что любопытное.

Ответом на вышеупомянутый вопрос было использование серии вызовов javascript в качестве URL-адресов для заполнения веб-формы и ее отправки. Я пытался сделать это автоматически в программе VB .NET безуспешно.

Исходный пример, который я привел, не работает, вероятно, потому, что вы ожидаете в том же потоке, в котором работает элемент управления WebBrowser:

WebBrowser1.Navigate("http://www.google.com")
Do While WebBrowser1.IsBusy OrElse WebBrowser1.ReadyState <> WebBrowserReadyState.Complete
    Threading.Thread.Sleep(1000)
Application.DoEvents()
Loop
WebBrowser1.Navigate("javascript:function%20f(){document.forms[0]['q'].value='stackoverflow';}f();")
Threading.Thread.Sleep(2000) 'wait for javascript to run
WebBrowser1.Navigate("javascript:document.forms[0].submit()")
Threading.Thread.Sleep(2000) 'wait for javascript to run

Если вы вообще не ждете, это тоже не сработает. URL-адрес, по которому вы первоначально просматриваете, прерван. Но, что интересно, вы также не можете выполнить «навигацию» к вызовам javascript без задержки.

Итак, я попробовал два других метода: использовать событие DocumentCompleted, чтобы дождаться просмотра URL-адреса гнезда, пока браузер не завершит загрузку страницы. К сожалению, DocumentCompleted не всегда срабатывает и, похоже, не срабатывает после каждого URL-адреса JavaScript.

Второй метод, который я попробовал, состоял в том, чтобы поместить ожидание в отдельный поток:

 Private Delegate Sub SetTextDelegate(ByVal TheText As String)
 Private Sub delSetText(ByVal TheText As String)
     WebBrowser1.Navigate(TheText)
 End Sub

 Private Sub BrowseTo(ByVal URL As String)
     If WebBrowser1.InvokeRequired Then
         Me.BeginInvoke(New SetTextDelegate(AddressOf delSetText), URL)
     Else
         WebBrowser1.Navigate(URL)
     End If
 End Sub

 Private Sub TargetURL()
   BrowseTo("http://www.google.com")
 End Sub

 Private Sub TypeSomethingIn()
     BrowseTo("javascript:function%20f(){document.forms[0]['g'].value='test';}f();")
 End Sub

 Private Sub SubmitForm()
     BrowseTo("javascript:document.forms[0].submit()")
 End Sub

 Private Sub Wait()
     While True
         If WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then Exit Sub
         Threading.Thread.Sleep(100)
     End While
 End Sub

 Private Sub AutoBrowse()
     TargetURL()
     Wait()
     TypeSomethingIn()
     Wait()
     SubmitForm()
 End Sub

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     Dim t As Threading.Thread
     t = New Threading.Thread(AddressOf AutoBrowse)
     t.Start()
 End Sub

Любопытно, что проверка ReadyState (или IsBusy, в этом отношении) в цикле ожидания иногда вызывает исключение InvalidCastException. Предположительно, звонки на них не безопасны? Я понятия не имею. Если я помещаю вызывающий вызов вызов в блок Try, цикл ожидания просто не работает. На самом деле, даже кажется, что исключение «сохраняется», чтобы все испортить, потому что даже при пошаговом выполнении кода с блоком try Visual Studio останавливается на добрые 10–20 секунд (то же самое происходит и без блока try).

Есть идеи?

Ответы [ 2 ]

4 голосов
/ 01 марта 2010

Одна из самых интересных проблем, с которыми я столкнулся не смог найти решение в инете - была проблема связанная с Веб-браузер управления. Дело в том, что когда я пытался получить доступ к Свойство документа экземпляра элемента управления WebBrowser, я получаю "Неверное исключение приведения". Дело в том, что элемент управления WebBrowser рассчитан на работу в один поток. Таким образом, чтобы исправить это, вы должны только проверить Свойство InvokeRequired и, если оно имеет значение true, вызывать логику от делегата, переданного в метод browser.Invoke (...).

Источник

1 голос
/ 21 февраля 2010

После msdn статьи: «В элементе управления есть четыре метода, которые можно вызывать потокобезопасно: свойство Invoke, BeginInvoke, EndInvoke и CreateGraphics и InvokeRequired»

Поэтому вызов WebBrowser1.ReadyState в Sub Wait не является потокобезопасным

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