Backgroundwoker funktionert nicht mit HttpWebRequest

  • VB.NET
  • .NET (FX) 4.0

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Backgroundwoker funktionert nicht mit HttpWebRequest

    Hallo zusammen,

    ich benutze aktuell zum ersten mal den Backgroundworker. Dieser soll eine Listview zeile für zeile durchgehen und pro Zeile ein WebRequest durchführen. Nach jeder Zeile möchte ich ein reportprogress aufrufen. Hier mal der Code der NICHT funktioniert:

    VB.NET-Quellcode

    1. 'Backgroundworker arbeitet
    2. Sub BgwDoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    3. 'Listview Item für Item durchgehen
    4. For x = 0 To lv.Items.Count - 1
    5. 'Deklaration Web Request
    6. Dim oh_request As HttpWebRequest
    7. Dim oh_response As HttpWebResponse = Nothing
    8. Dim oh_reader As StreamReader
    9. Dim server_string As String = "http://" & server_name & ":" & server_port & "/item/" & lv.Items(x).Text
    10. 'Response auf Request empfangen
    11. oh_request = DirectCast(WebRequest.Create(server_string), HttpWebRequest)
    12. oh_response = DirectCast(oh_request.GetResponse(), HttpWebResponse)
    13. oh_reader = New StreamReader(oh_response.GetResponseStream())
    14. oh_request.timeout = 5000
    15. 'Response in String schreiben
    16. Dim raw_oh_response As String
    17. raw_oh_response = oh_reader.ReadToEnd()
    18. bgw.ReportProgress(x)
    19. Threading.Thread.Sleep(1000)
    20. Next
    21. End Sub
    22. 'Backgroundworker Prozess geändert
    23. Sub BgwProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs)
    24. Dim wert As Integer = e.ProgressPercentage
    25. messagebox.Show(wert.ToString)
    26. End Sub
    27. 'Backgroundworker ist fertig
    28. Sub BgwRunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs)
    29. MessageBox.Show("Fertig")
    30. End Sub


    Dieser Code funktioniert dagegen:

    VB.NET-Quellcode

    1. 'Backgroundworker arbeitet
    2. Sub BgwDoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
    3. 'Listview Item für Item durchgehen
    4. For x = 0 To lv.Items.Count - 1
    5. bgw.ReportProgress(x)
    6. Threading.Thread.Sleep(1000)
    7. Next
    8. End Sub
    9. 'Backgroundworker Prozess geändert
    10. Sub BgwProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs)
    11. Dim wert As Integer = e.ProgressPercentage
    12. messagebox.Show(wert.ToString)
    13. End Sub
    14. 'Backgroundworker ist fertig
    15. Sub BgwRunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs)
    16. MessageBox.Show("Fertig")
    17. End Sub


    Beim ersten Code erhalte ich nur die "Fertig" Messagebox wenn der Bgw completed ist. Beim zweiten Code erhalte ich für jede Zeile meiner Listview eine Messagebox und dann die bgw completed Messagebox. Der Unterschied besteht ja nur im fehlenden WebRequest.

    Ich stehe mal wieder auf dem Schlauch und hoffe mich kann jemand auf meinen Fehler hinweisen.

    Gruß Kay
    @kayle WebRequest kannst Du asynchron machen, da brauchst Du keinen BGW.
    Gugst Du z.B. hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    kayle schrieb:

    Backgroundworker
    ist ein lebendes Fossil, heutzutage gibt es da bessere Parallel-Abarbeitungs-Methoden (Async / Await).
    WWW-Zugriffe bieten von sich aus asynchrone Methoden an, da ist es sehr sinnvoll, Frau Google und die MSDN nach zu befragen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo @RodFromGermany und @ErfinderDesRades

    ich habe den Download des Strings nun mittels Webclient und Download Async String gemacht. Das funktioniert schon prima. Danke für den Tip. Jetzt habe ich aber ein weiteres Problem. Der Json String wird nun mittels Newtonsoft json geparst und in eine Listview geschrieben. Dabei friert die GUI für 2 Sekunden ein. Was wäre jetzt die bessere Methode das zu umgehen ? Backgroundworker, wenn auch alt oder separaten Thread ?

    Gruß Kay

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „kayle“ ()

    Ist das noch nicht deutlich geworden?
    Streich mal das Wort "BackgroundWorker" aus deinem Wortschatz. Danke.

    Und statt was mit Threads zu basteln arbeite dich in den Async-Pattern ein - das ist zum Schreien einfach, und ist eh ein "Must-Know" - lange bevor du iwas mit Threads anfasst.
    Hier ein englisches Tut, womit auch ein Anfänger klarkommen sollte - dein Thema ist da im ersten Abschnitt abgehandelt.

    Oder Zeige Code, wie du die Json-Parse-Methode aufrufst, dann schreib ichs dir mit Async.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    ErfinderDesRades schrieb:

    Streich mal das Wort "BackgroundWorker" aus deinem Wortschatz. Danke.


    Ok, ist geschehen :thumbup:

    ErfinderDesRades schrieb:

    Oder Zeige Code, wie du die Json-Parse-Methode aufrufst, dann schreib ichs dir mit Async.


    VB.NET-Quellcode

    1. 'WebClient Async Downloadstring
    2. 'Test Async
    3. 'Kay P.
    4. '01.04.2017
    5. 'Imports
    6. Imports System.Net
    7. Imports Newtonsoft.Json
    8. Imports Newtonsoft.Json.Linq
    9. Public Partial Class MainForm
    10. Public Sub New()
    11. Me.InitializeComponent()
    12. End Sub
    13. 'Mit Button Click wird der Webclient erstellt und der Download String Async angestoßen
    14. Sub Button1Click(sender As Object, e As EventArgs)
    15. Dim webclient As New WebClient
    16. AddHandler webClient.DownloadStringCompleted, AddressOf webClient_DownloadStringCompleted
    17. webclient.DownloadStringAsync(New Uri("http://10.23.59.70:8080/rest/items/"))
    18. End Sub
    19. 'Webclient ist fertig und Json Daten werden in das ListView geschrieben
    20. Private Sub webClient_DownloadStringCompleted(ByVal sender as Object,ByVal e as DownloadStringCompletedEventArgs)
    21. 'JSON Daten von OH REST API 2.x auslesen
    22. Dim rest_api_result = JsonConvert.DeserializeObject(Of ArrayList)(e.Result)
    23. Dim token As JToken
    24. 'Für jede Node ein Item in der ListView erstellen
    25. For Each value As Object In rest_api_result
    26. token = JObject.Parse(value.ToString())
    27. Dim subitem As ListViewItem
    28. With oh_item_list.Items
    29. subitem = .Add(token.SelectToken("name").ToString)
    30. subitem.SubItems.Add(token.SelectToken("type").ToString)
    31. End With
    32. Next
    33. End Sub
    34. End Class


    Gruß Kay

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „kayle“ () aus folgendem Grund: Formatierung Quellcode bearbeitet

    VB.NET-Quellcode

    1. 'Webclient ist fertig und Json Daten werden in das ListView geschrieben
    2. Private Sub webClient_DownloadStringCompleted(ByVal sender as Object,ByVal e as DownloadStringCompletedEventArgs)
    3. 'JSON Daten von OH REST API 2.x auslesen
    4. Dim rest_api_result = parse_json(e.Result)
    5. Dim token As JToken
    6. 'Für jede Node ein Item in der ListView erstellen
    7. For Each value As Object In rest_api_result
    8. token = JObject.Parse(value.ToString()
    9. Dim subitem As ListViewItem
    10. With oh_item_list.Items
    11. subitem = .Add(token.SelectToken("name").ToString)
    12. subitem.SubItems.Add(token.SelectToken("type").ToString)
    13. End With
    14. Next
    15. End Sub
    16. 'Json Parse Function
    17. Public Function parse_json(ByVal raw_string As String) As ArrayList
    18. Dim api_result = JsonConvert.DeserializeObject(Of ArrayList)(raw_string)
    19. Return api_result
    20. End Function


    Habe den Json Parse Teil nun in eine Function ausgelagert. Und diese Function kann ich jetzt asynchron aufrufen ?

    kayle schrieb:

    Habe den Json Parse Teil nun in eine Function ausgelagert.
    Hast du nicht (oder nur halb).

    Nachwievor findet sich

    VB.NET-Quellcode

    1. token = JObject.Parse(value.ToString()
    beim Aufrufer.
    Ich sagte doch, deine methode solle eine List(Of JObject) zurückgeben, warum gibt sie nu eine dumme ArrayList zurück, wo noch weiter dran herumgeparst werden muss?
    Das Weiter-Rum-parsen gehört auch in parse_Json() hinein, und erfolgt im nächsten Schritt dann nebenläufig.