Nowy wątek, obiekt z formy głównej.

0

Witam,

Z Visual Basic mam do czynienia od kilku dni, wcześniej uczyłem się programować na Dev C++ więc myślę że jestem w stanie napisać jakiś prosty dosyć program.

Mój problem polega na tym gdyż tworzenie nowego wątku sprawia mi problem, obiekt który należy do głównego wątku w moim przypadku jest to WebBrowser odmawia współpracy z świeżo stworzonym wątkiem (inne obiekty typu TextBox'y działają prawidłowo).
Cały program bez tworzenia nowego wątku działa podczas Debugowania, niestety operacje jakie wykonuje są w nieskończonej pętli od czasu uruchomienia. Sprawia to że śledzenie aktualnej pracy programu jest nie możliwe, jedynym sposobem który pozwalał mi sprawdzić czy program dochodzi do jakiegoś momentu było wstawienie MsgBox'ów.

Kod błędu jaki wskazuje mi Debuger jest następujący:

An unhandled exception of type 'System.InvalidCastException' occurred in System.Windows.Forms.dll

Additional information: Określone rzutowanie jest nieprawidłowe.

Szukałem informacji na ten temat w internecie lecz niestety nie natrafiłem na informacje który byłby w moim przypadku pomocne, jako że pierwszy raz mam styczność z wielozadaniowością ciężko jest mi zrozumieć w czym może tkwić problem. Doczytałem się jedynie że podczas korzystania z wątków nie może być w tym samym momencie wykorzystywany dany obiekt, w moim przypadku wątek jedynie przelicza oraz wprowadza dane do formy kiedy to główny wątek jedynie wyświetla ową formę i nie ingeruje w jej działanie (przynajmniej tak mi się wydaje).

Poniżej zamieszczam trochę kodu z mojego programu, jest w nim między innymi przycisk tworzący oraz uruchomiający nowy wątek, oraz część kodu owego wątku na którym Debuger się krzaczy.

Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
        trd = New Thread(AddressOf ThreadTask)
        trd.IsBackground = True
        trd.Start()
End Sub

Oraz rozpoczynający się wątek:

Private trd As Thread

Public Sub ThreadTask()

WebBrowser1.Navigate("przykladowa-strona.pl")
System.Threading.Thread.Sleep(3000) ' Tutaj czekam chwilę aż strona się załaduje

Dim theElementCollection As HtmlElementCollection
        theElementCollection = WebBrowser1.Document.GetElementsByTagName("input")
        For Each curElement As HtmlElement In theElementCollection
            Dim controlName As String = curElement.GetAttribute("name").ToString
            If controlName = "code" Then
                curElement.SetAttribute("value", Klucz())
            End If
        Next

Sposób tworzenia wątków znalazłem na MSDN z którego skorzystałem, czytałem także o Invoke oraz Delegate lecz po kilku próbach ich wykorzystania porzuciłem nadzieję w tym.

Kod do pobierania strony oraz parsowanie jej w celu znalezienia każdego input'u a następnie konkretnej informacji i zmienienia jej znalazłem na internecie i starałem się ją zrozumieć zanim użyłem.
Dodam że program krzaczy się w momencie gdy zmienna theElementCollection próbuje załadować WebBrowser1.Document.GetElementsByTagName("input") (bynajmniej debuger wskazuje mi tą linijkę).

Mam nadzieję że ktoś będzie w stanie wskazać mi problem oraz pomóc w jego rozwiązaniu, jako że jestem początkującym programistą który nie miał jeszcze przyjemności korzystania z VB liczę na wyrozumiałość.

Także jakby ktoś miał pomysł, jeżeli jest sposób na uruchomienie kodu bez tworzenia nowych wątków tak aby obiekt (tak nazywam formę WebBrowser) potrafił cały czas trwania programu odświeżać się i nie powodować tracenia kontaktu pomiędzy Interfejsem a Użytkownikiem.

Pozdrawiam,
Kameha

0
  1. Nie rozumiem po co chcesz tworzyć nowy wątek dla webrowsera. W przypadku tej kontrolki proces ładowania strony odbywa się w osobnym wątku.
  2. System.Threading.Thread.Sleep(3000) ' Tutaj czekam chwilę aż strona się załaduje - Niestety ale nie można tak robić ponieważ nie wiesz czy faktycznie strona została załadowana. Do tego służy event DocumentCompleted.
  3. Jeśli już chcesz coś robić wielowątkowego to raczej poczytałbym na temat Task.

Kod powinien wyglądać tak:

    Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted

        Dim browser As WebBrowser = DirectCast(sender, WebBrowser)
        Dim theElementCollection As HtmlElementCollection = browser.Document.GetElementsByTagName("input")

        For Each curElement As HtmlElement In theElementCollection
        ....        
        Next


    End Sub

1 użytkowników online, w tym zalogowanych: 0, gości: 1