Asynchrone HttpWebRequests und Yield

  • VB.NET
  • .NET (FX) 4.5–4.8

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

    Asynchrone HttpWebRequests und Yield

    Hallo.

    Ich frage mich, welches die beste Lösung für mein Vorhaben ist.
    Nebeninfo: Ich nutze eine Windows Forms Anwendung (ja, ich weiß, WPF und so.. bitte erschlagt mich nicht :D)

    Was habe ich vor ?

    Ich möchte auf einer Website Daten sammeln, ziemlich viele sogar.
    Ich spreche von ungefähr 2.000.000 Strings, jeder kann minimal 3
    und maximal 15 Zeichen lang sein.

    Wie werden die Daten herangezogen?

    Per HttpWebRequest. Sowohl GET als auch Antworten von POST Requests.
    Pro Request erhalte ich ungefähr 20-25 Ergebnisse.

    Gibt es Einschränkungen serverseitig?

    Ja. Die Requests dürfen nicht zu schnell nacheinander gemacht werden.


    Der Grund warum ich frage ist: Ich denke, dass
    ich noch etwas performance rausholen kann. Aktuell
    habe ich eine Funktion, die mir immer ein Tuple(of String, String) per yield gibt.
    Sprich immer wenn zwei Strings verfügbar sind, yielde ich direkt.
    Das läuft schon wirklich sehr gut, aber mit dem Gedanken, dass
    die Requests synchron sind, kann ich mich noch nicht anfreunden.
    Ebenfalls habe ich den Eindruck, dass das GUI etwas hängt ab und zu,
    ich denke das liegt auch an den Requests (merkt man auch beim Login auf der Page, sprich
    genau wenn der Login Request abgesendet wird).

    Was würdet ihr vorschlagen, wie kann man bestmögliche Performance rausholen?
    Damit deine UI nicht hängt könntest du etwas schreiben wie:

    C#-Quellcode

    1. response = await request.GetResponseAsync();


    Mit await wird gewartet, ohne das deine UI blockiert... Der Response läuft async im hintergrund.
    NETworkManager - A powerful tool for managing networks and troubleshoot network problems!

    BornToBeRoot schrieb:

    [...]
    Mit await wird gewartet, ohne das deine UI blockiert... Der Response läuft async im hintergrund.




    So leicht ist es dann leider doch nicht.


    Man muss schauen, in welchem Kontext die asynchronen Calls ablaufen.

    Wichtig in diesem Zusammenhang ist ja:

    VB.NET-Quellcode

    1. ConfigureWait(False)

    Um deadlocks zu vermeiden.

    Ich hab da sowas gesehen wie:

    VB.NET-Quellcode

    1. var jsonString = Await client.GetStringAsync(uri).ConfigureAwait(False)
    2. Return JObject.Parse(jsonString)




    Meine Funktion sieht so aus:

    VB.NET-Quellcode

    1. Private Shared Function Req(Site As String, Optional Met As String = "GET", Optional P As String = "") As HttpWebRequest
    2. Met = Met.ToUpper
    3. Dim R As HttpWebRequest = CType(HttpWebRequest.Create(Site), HttpWebRequest)
    4. With R
    5. .Proxy = Nothing
    6. .Method = Met
    7. .CookieContainer = Session.Containa
    8. .AllowAutoRedirect = True
    9. .UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36"
    10. .ContentType = "application/x-www-form-urlencoded"
    11. .Timeout = 20000
    12. .ServicePoint.ConnectionLimit = 65000
    13. ServicePointManager.DefaultConnectionLimit = 65000
    14. ServicePointManager.Expect100Continue = False
    15. End With
    16. Util.HelpSub(Site, P, Met, True)
    17. If Met = "POST" AndAlso P.Length > 0 Then
    18. R.ContentLength = P.Length
    19. Using Wr As New StreamWriter(R.GetRequestStream(), Encoding.Default)
    20. Wr.Write(P)
    21. Wr.Close()
    22. End Using
    23. End If
    24. Return R
    25. End Function


    Und dann gibt es diverse Unterfunktionen, die den HttpWebRequest unterschiedlich verwenden.


    Zum Beispiel:


    VB.NET-Quellcode

    1. Public Shared Function ReqF(Site As String, Optional Met As String = "GET", Optional P As String = "") As String
    2. Dim R As HttpWebRequest = Req(Site, Met, P)
    3. Using Re As New StreamReader(R.GetResponse.GetResponseStream())
    4. Return Re.ReadToEnd
    5. Re.Close()
    6. End Using
    7. End Function



    Kann mir da jemand sagen, wie das bei meinen Funktionen dann laufen würde?

    Die sind ja schon aufgesplittet und ich denke, da muss man das dann etwas anders machen..