Max Threats (Task.run)

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von XBrainBug.

    Max Threats (Task.run)

    Hallo,

    ​ich möchte gerne alle IP´s meines Subnetzes anpingen und das möglichst schnell. Also habe ich mich für Task.run entschieden und das in eine For each Schleife gelegt. Es klappt auch soweit ganz gut, bis darauf das nur Maximal 4 Threats zugleich bearbeitet werden, wenn ich AWAIT benutze sogar nur 2 Threats. Ich habe mal etwas von Threatpool gelesen, wäre das vielleicht besser oder gibt's irgendwo etwas wo ich die Maximalen Threats hochstellen kann?!

    Mit AWAIT:

    VB.NET-Quellcode

    1. Private Async Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. For i = 0 To 30
    3. Dim o As String = i
    4. Await Task.Run(Sub()
    5. If My.Computer.Network.Ping("10.10.4." & o, 100) Then
    6. Me.Invoke(New ChangeLabelText(AddressOf Meldung), "IP: " & o & " war erfolgreich")
    7. Else
    8. Me.Invoke(New ChangeLabelText(AddressOf Meldung), "IP: " & o & " war nicht erfolgreich")
    9. End If
    10. End Sub)
    11. Next
    12. Task.WaitAll()
    13. End Sub


    Ohne Await:

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. For i = 0 To 30
    3. Dim o As String = i
    4. Task.Run(Sub()
    5. If My.Computer.Network.Ping("10.10.4." & o, 100) Then
    6. Me.Invoke(New ChangeLabelText(AddressOf Meldung), "IP: " & o & " war erfolgreich")
    7. Else
    8. Me.Invoke(New ChangeLabelText(AddressOf Meldung), "IP: " & o & " war nicht erfolgreich")
    9. End If
    10. End Sub)
    11. Next
    12. End Sub

    XBrainBug schrieb:

    das nur Maximal 4 Threats zugleich bearbeitet werden
    Wieviele Kerne hat der Prozessor Deines PCs?
    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!
    Task.Run bzw. Tasks arbeiten ohne weitere Hinweise auf folgende Art und Weise:
    Es wird ein Task erstellt, der im GUI Thread läuft, nur dass dank Concurrency nun abwechselnd der Task und die GUI in diesem Thread ausgeführt werden. So wird auf der einen Seite die GUI nicht blockiert wenn nur geringe CPU Last anliegt, auf der anderen Seite spart man sich einen extra Thread mit all seinen unannehmlichkeiten. Stellt sich nun heraus, dass der Task entweder über längere Zeit läuft oder hohe CPU-Last erzeugt, so kann dieser Task auf einen Thread ausgelagert werden. Wie und wann das passiert ist komplett der CLR überlassen.

    Dass bei deinem Ping beispiel überhaupt noch ein weiterer Thread erzeugt wird, liegt wohl daran, dass so viele Tasks nicht in einen Thread passen, oder aber die CLR erkennt, dass die Pings lange dauern.
    Kannst ja spaßeshalber innerhalb des Tasks mal i via System.Diagnostics.Debug.WriteLine() innen Output/Ausgabe schreiben lassen.
    @RodFromGermany
    Ja daran habe ich auch schon gedacht aber ich habe 4 Cores mit HyperThreding, also sollte er doch 8 schaffen (Theoretisch) aber warum er mit Await nur noch 2 macht ist noch unverständlicher für mich

    @petaod Ja das habe ich auch schon gesehen aber hatte nichts gescheites gefunden. Aber habe noch mal gesucht und ein Paar Beispiele gefunden, werde es erstmal damit testen.

    @EaranMaleasi
    Danke werde ich mal testen.
    Ich habe auch einen anderen Befehl, der mir locker 20 Nachrichten mit MSG.exe raus schickt und bei jeden Task auf Antwort wartet, was 60 Sekunden dauern kann, und das zugleich, also nicht nur 4 Stück. Deshalb verstehe ich nicht warum er hier nur 4 raus schickt.


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

    Hab die Lösung gefunden, das ganze braucht jetzt noch ca. 1 Sekunde für 1016 IP Adressen.

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. For n = 0 To 4
    3. For i = 0 To 254
    4. Dim ping As New Net.NetworkInformation.Ping()
    5. AddHandler ping.PingCompleted, AddressOf Ping_Completed
    6. ping.SendAsync("10.10." & n & "." & i, Nothing)
    7. Next
    8. Next
    9. End Sub
    10. Private Sub Ping_Completed(sender As Object, e As Net.NetworkInformation.PingCompletedEventArgs)
    11. If e.Error Is Nothing AndAlso e.Reply.Status = Net.NetworkInformation.IPStatus.Success Then
    12. Me.Label_Meldung.Text += "IP: " & e.Reply.Address.ToString & " war erfolgreich" & vbCrLf
    13. End If
    14. End Sub

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

    XBrainBug schrieb:

    For n = 0 To 4
    For i = 0 To 254
    Dim ping As New Net.NetworkInformation.Ping()
    AddHandler ping.PingCompleted, AddressOf Ping_Completed

    Strange.
    Du erzeugst 1016 Ping-Objekte und 1016 Handler.
    Hast du auch mal versucht nur eine Instanz zu verwenden?
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    jo, das meint er wohl.
    Noch kleine Korrektur:

    petaod schrieb:

    Du erzeugst 1016 Ping-Objekte und 1016 Handler.
    1016 Ping-Objekte muss er wohl erzeugen, wenn die gleichzeitig los-pingen sollen.
    Aber Handler hatter ja nur einen, worauf er alle Ping_Completed-Events leitet.
    Also ich finde das eine perfekte Lösung.
    Ich bin eiglich überrascht, dass die INet-Anbindung das zulässt - zumindest wenn man WebSiten connecten will, gibts da rigorose Einschränkungen der Parallelität.
    Bei meinem NETworkManager habe ich eine Parallel.ForEach (MSDN) für den IP-Scanner genommen. Du musst mit MaxDegreeOfParallelism die Obergrenze festlegen und den ThreadPool entsprechend anpassen, da dieser sich an der CPU orientiert...

    Threadpool anpassen:

    C#-Quellcode

    1. ThreadPool.GetMinThreads(out int workerThreads, out int completionPortThreads); // Default speichern
    2. ThreadPool.SetMinThreads(workerThreads + 256, completionPortThreads + 256); // 256 entspricht /24 ggf. anpassen


    und danach wieder Rückgängig machen...

    C#-Quellcode

    1. ThreadPool.SetMinThreads(workerThreads, completionPortThreads); // Reset


    Hier meine Source: github.com/BornToBeRoot/NETwor…dels/Network/IPScanner.cs


    Das praktische... du kannst mehrere Sachen machen und nicht nur einen Ping senden... z.B. DNS, ARP, Hersteller der MAC suchen...

    XBrainBug schrieb:

    Hab die Lösung gefunden, das ganze braucht jetzt noch ca. 1 Sekunde für 1016 IP Adressen.


    Du machst wahrscheinlich nur einen Ping und hast den Timeout auf 1000ms gesetzt? Ich würde dir empfehlen, um die Genauigkeit zu verbessern den Timeout auf 4000ms (vergleichbar ping.exe default) zu setzten und mindestens 2 Pings zu machen (manchmal antwortet der erste nicht).



    Btw: Es ist auch Möglich mit einem RunspacePool (PowerShell): github.com/BornToBeRoot/PowerS…ripts/IPv4NetworkScan.ps1

    Gruß
    BornToBeRoot
    NETworkManager - A powerful tool for managing networks and troubleshoot network problems!
    @XBrainBug Ich hatte mal mit nem Multi-Download probleme. Gugst Du dazu hier: Multi-Download nur im Doppelpack
    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!
    @ErfinderDesRades
    Ja das es geht hat mich auch überrascht, also alles auf einmal. Ich dachte das es da schon irgendwo grenzen geben müsste aber die scheinen wohl nur noch Hardwaretechnisch zu sein.

    @BornToBeRoot Das hört sich sehr interessant an. Mein Ziel ist eigentlich ein Programm was NetSend ersetzen soll und mit Bordmitteln arbeitet. Das heißt das ich nach dem ich alle aktiven IP´s habe, die Benutzer per WMI abfragen will. Die Abfrage ich schon fertig aber sie ist nicht wirklich schnell. Deshalb hört sich
    Das praktische... du kannst mehrere Sachen machen und nicht nur einen Ping senden... z.B. DNS, ARP, Hersteller der MAC suchen...
    sehr nach etwas an, was mir helfen könnte.

    @RodFromGermany
    Das könnte auch bei der nächsten Sache mit WMI Helfen.


    Wenn das mit WMI auch noch schnell geht, habe ich ein Tool was im angegeben Bereich nach aktiven IP´s sucht, die Namen der Benutzer ermittelt, mir eine Liste gibt wo ich die Benutzer auswählen kann. Dann kann ich Nachrichten verschicken und erfahre sogar wer sie weg geklickt hat("gelesen"). Und wer mal wieder nicht am Platz war..... :D Und das alles ohne zusätzliche Tools!

    XBrainBug schrieb:

    Mein Ziel ist eigentlich ein Programm was NetSend ersetzen soll und mit Bordmitteln arbeitet.


    Wenn das ein lokaler Chat werden soll, würde ich mir den Multiserver (TCP) im Sourcecode austausch mal anschauen.

    Solltest du es wirklich mit Boardmitteln machen, lass die Finger weg von Wmi. Die msg.exe kann auch Nachrichten anzeigen.

    Hab hier nur ein PowerShell-Codeschnipsel, aber der Aufruf sollte klar sein:

    Quellcode

    1. if (Test-Connection -ComputerName $hostname -Quiet -Count 1)
    2. {
    3. msg.exe $username /SERVER:$hostname /TIME:86400 (Read-Host "Nachricht")
    4. }


    Anstatt Username kannst du auch * eintragen, somit wird die Nachricht an alle Sessions geschickt, die auf dem PC/Server aktiv sind (an PCs sollte ja nur eine Person angemeldet sein). Bei Terminalservern mit X Nutzern, würde ich dann doch den Benutzernamen bevorzugen.
    NETworkManager - A powerful tool for managing networks and troubleshoot network problems!
    @BornToBeRoot
    ​Ja ich benutze schon MSG.exe, WMI ist zum rausfinden welche Benutzer an dem PC angemeldet ist. Damit MSG.exe funktioniert brauche ich PC oder IP und den Benutzer an den Rechner angemeldet ist, sonst geht's nicht. Und da ich keine DB, Startscripte etc nutzen will, muss ich es live abfragen. Eigentlich funktioniert das ja alles schon, nur die Geschwindigkeit bei WMI ist noch ein Problem. Ich werde morgen erstmal weiter testen wie ich WMI auch Parallelisieren kann. Ziel ist das er mir in unter 5 Sek. alle Rechner mit IP und Benutzernamen im Netzwerk in einem DataGridView anzeigt. Aber eine WMI Abfrage kann locker schon 5 Sekunden dauern.