Maximales Limit an geöffneten WinForms-Anwendungen unter Windows?

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von MrTrebron.

    Maximales Limit an geöffneten WinForms-Anwendungen unter Windows?

    Hallo liebe Foren-Gemeinde,

    ich habe einen sehr umfangreichen Crawler in .NET 4.5 geschrieben, welcher auf einem großen Root-Server läuft (128 GB Ram, 128 IPs).
    Nun habe ich das Programm so konzipiert, dass ich ein Hauptprogramm habe (eigenständige .exe), von dem aus ich "Clients" aus starten und stoppen kann. (Die Clients sind jeweils ebenfalls eine WinForms .exe).
    Leider ist es so, dass wenn ich insgesamt ungefähr 1500 Clients geöffnet habe das Hauptprogramm aus geht und auch Windows komplett ausgelastet ist und alles sehr verzögert durchgeführt wird. Sobald ich wieder einige Clients (Programme) schließe, wird Windows wieder bedienbar und alles Programme laufen komplett normal. Vor dieser Root-Server Lösung habe ich mehrere VPS (Virtuelle Maschinen) gehabt, auf denen die Clients verteilt liefen. Dort konnte ich ohne Probleme 3000 Clients verteilt öffnen ohne dass das Hauptprogramm instabil wurde. Jedoch musste ich dort zeitweise auf 50 VPS neue Updates installieren und die Wartungsarbeiten waren einfach nicht mehr machbar.

    Nun möchte ich mir nicht die Arbeit machen und die Clients quasi als eigene Threads in das Hauptprogramm zu integrieren, weil ich dann befürchte das unsichtbares Thread-Blocking das ganze stark in der Performance reduziert.

    Gibt es irgendwelche Limits, dass Windows 1500 gleiche Programme nicht mehr handlen kann? Ich habe TCP-Server Probleme schon ausgeschlossen, denn auch wenn ich das Ping-Verfahren zwischen Client und Server abgeschaltet habe und quasi die Clients unabhängig vom Hauptprogramm liefen, war bei 1500 Schluss. Wenn ich 2 Hauptprogramme starten und jeweils 750 Clients laufen lasse, ist es ebenfalls das Maximum und alles schmiert ab.

    Ich habe mich die letzten Wochen intensiv darum bemüht, alles auf einen Root-Server auszulegen und ich hoffe ich habe das jetzt nicht komplett umsonst gemacht. Mir fällt auch irgendwie kein passender Suchbegriff für Google ein, weil wenn ich Max-Threads Windows eingebe, wird meistens auf das ThreadLimit von Threadpools verwiesen.

    Vielleicht hat der ein oder andere eine Idee, was das Limit sein könnte.

    Verwendete Technologien:
    HttpClient (für Webrequests)
    .NET.Sockets

    Server:
    Windows Server 2012 R2
    128 GB Ram
    Intel XeonE5-1650v26C 3,5 GHz+/3,9 GHz+

    Warum reicht es nicht, dass das Hauptprogramm WinForms ist? Die anderen brauchen doch nicht extra etwas anzeigen, kann ja alles in der Hauptanwendung gesammelt werden.
    Außerdem denke ich, dass einzelne Prozesse das ganze eher verlangsamen als Threading(vorrausgesetzt richtig implementiert natürlich).
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Angezeigt wird in der Tat nichts. Entstanden ist das Ganze in diesem Konzept, weil ich es leichter finde einzelne Anwendungen zu debuggen, als wenn man beim Multithreading die ganze Zeit zwischen 100 Threads hin und herspringen muss und außerdem bin ich einfach super misstrauisch ob die Threads tatsächlich auch in der gewünschten Art die Arbeit machen, die sie sollen. Kurz: Ich bin mit Multithreading noch nicht wirklich warm geworden :whistling: Rein theoretisch könnte ich natürlich den Client-Code in einem neuem Namespace implementieren und aus dem Hauptprogramm aus laufen lassen, bloß noch will ich das jetzige Konzept nicht gänzlich aufgeben weil es ja prinzipiell einwandfrei läuft (bis 1500 pro Server), außer ihr haut jetzt so lange auf mich ein, dass ich von selbst das ganze in da Hauptprogramm stecke :D

    Was würdest du mir empfehlen jvbsl? Einen Threadpool erstellen und dort alle Client-Threads reinschmeissen und das ganze aus dem Hauptprogramm laufen lassen?
    Danke schonmal für die Antwort :)
    Du kannst das trotzdem in einem extra Projekt lassen und zu ner DLL zusammenfassen, die du dann in dein Hauptprogramm integrierst.

    Ich kann so erstmal gar nichts empfehlen, weil ich überhaupt nicht weiß, was ein einzelnes solches Programm denn überhaupt macht.
    Und ich frage mich sowieso, wenn es jedesmal dasselbe Programm ist, wer braucht 1500 unterschiedliche Tcp Verbindungen?
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Ich habe einmal eine grobe Skizze gemacht von meinem Konstrukt.


    Jeder Client hält zu dem Control-Programm eine TCP-Verbindung und sendet auf Anforderung des Hauptprogrammes einen Ping (alle 15 Sek.)
    Das Hauptprogramm beinhaltet die Möglichkeit auf verschiedenen Servern Clients zu starten, wobei jeder Client eine unterschiedliche Aufgabe hat. (Aufgabe = Webseite nach neuen Inhalten checken).
    Lokal, also auf dem Server, wo das Control-Programm läuft, kann ich direkt die Bot.exe starten und wenn das ganze serverübergreifend gestartet werden soll, habe ich einen sogenannten Unter-Server laufen, der einfach den Startbefehl des Hauptprogrammes auf dem Server ausführt und die Bot.exe dort startet.
    Du könntest damit anfangen die Sockets zur Kommunikation durch sogenannte pipes auszutauschen, dann wird damit schon mal die Anzahl der Tcp verbindungen gesenkt.
    Was du mit deinen Sockets machst ist Prozess Synchronisation, was anderes müsstest du für Threads auch nicht machen, wobei dort Events+mutex (u.ä.) vmtl die bessere Wahl wären.
    Hast du irgendeine Art Log, warum das ganze Überhaupt abschmiert? Dasolllte doch irgendeine Art Meldung kommen.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Durch Tests konnte ich Fehler bei den TCP-Verbindungen komplett ausschliessen.

    Mit folgenden Programmen, habe ich den Fehler stark vereinfacht simuliert:

    Programm, welches die Clients startet (Textbox ist die Anzahl)

    VB.NET-Quellcode

    1. ​[/b]Public Class Form1
    2. Private Sub cmdStart_Click(sender As Object, e As EventArgs) Handles cmdStart.Click
    3. Dim Programm As String = Application.StartupPath + "\Test.exe"
    4. For i As Integer = 0 To txt_StartForms.Text
    5. Process.Start(Programm)
    6. Threading.Thread.Sleep(100)
    7. lbl_StartedCount.Text = (i + 1).ToString
    8. Next
    9. End Sub
    10. Private Sub cmdKillProcesses_Click(sender As Object, e As EventArgs) Handles cmdKillProcesses.Click
    11. For Each P As Process In System.Diagnostics.Process.GetProcessesByName("Test")
    12. P.Kill()
    13. Next
    14. End Sub
    15. End Class[b]



    Das ist der Client

    VB.NET-Quellcode

    1. ​Public Class Form1
    2. Dim WithEvents TestClass As New DoRandomStuff
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. WindowState = FormWindowState.Minimized
    5. Timer1.Start()
    6. End Sub
    7. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    8. Dim thread As New Threading.Thread(Sub() TestClass.Start())
    9. thread.Start()
    10. Timer1.Stop()
    11. End Sub
    12. Private Sub Test_Test(Counter As Integer) Handles TestClass.CounterUP
    13. Me.Invoke(Sub() Label1.Text = Counter.ToString)
    14. End Sub
    15. End Class
    16. Public Class DoRandomStuff
    17. Public Event CounterUP(Counter As Integer)
    18. Public Sub Start()
    19. While True
    20. For i As Integer = 0 To 15
    21. RaiseEvent CounterUP(i + 1)
    22. Threading.Thread.Sleep(500)
    23. Next
    24. End While
    25. End Sub
    26. End Class


    Wenn ich 1400-1500 Clients erreiche schmiert mein gesamter Server ab und im Server-Manager finde ich folgendes:

    Name des fehlerhaften Moduls: KERNELBASE.dll, Version: 6.3.9600.16656, Zeitstempel: 0x531812f4
    [15:22:01] Sven: NS344755 41 Kritisch Microsoft-Windows-Kernel-Power System 08.02.2015 14:20:06
    Die Frage ist, ob die Anzahl der Verbindungen Probleme macht.
    Und du da gibt es keine weiteren Details? Vlt. Steht auch was in der Ereignianzeige?(kp wo man bei win überall gucken kann)
    Edit: Als du gesagt hattest es wird nichts angezeigt, dachte ich du hättest keine UI.
    Entferne am besten aus den clients die anzeige und speicher das in variablen. Die serveranwendung kann dann bei bedarf diese abfragen und auf ihrer gui anzeigen (gewählt aus einer liste der laufenden Clients)
    Außerdem solltest du das schließen auch aus den Clients heraus machen (durch eine Nachricht vom Server)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

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

    Servus,

    Schau dir mal die GDI Handles an. Bei wie vielen schmiert er ab?

    Nutze auch mal procdump um dir einen Crashdump erstellen zu lassen.

    Was sagt der Dump?
    Die deutsche Sprache ist Freeware, du kannst sie benutzen, ohne dafür zu bezahlen. Sie ist aber nicht Open Source, also darfst du sie nicht verändern, wie es dir gerade passt.