![]() |
Re: Selbstgebauter Threadpool funktioniert nicht
Zitat:
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
Sollte das nicht reichen, dann kann ich notfalls auch die 2 Units anhängen..
// Wird im Mainthread aufgerufen
procedure TServerSocket.Listen; var id: Cardinal; begin FClosed := false; FSocket.Open; BeginThread(nil,0,@TServerSocket_CheckData,Self,0,id); BeginThread(nil,0,@TServerSocket_Listen,Self,0,id); end; procedure TServerSocket_CheckData(Server: TServerSocket); var i: Integer; begin with Server do begin while not FClosed do begin for i := FClients.Count-1 downto 0 do if FClients[i].DataAvailable then FThreadPool.AddJob(FClients[i]); sleep(1); end; end; end; // Der Threadpool procedure TThreadPool.AddJob(AJob: TObject); begin PostQueuedCompletionStatus(FIOComPort,SizeOf(TObject),Cardinal(AJob),nil); end; procedure TThreadPoolThread.GetJob; var bytes: Cardinal; over: POverlapped; AJob: Cardinal; begin if GetQueuedCompletionStatus(FIOComPort,bytes,AJob,over,0) then FJob := TObject(AJob) else FJob := nil; end; procedure TThreadPoolThread.Execute; begin while not FDead do begin GetJob; if (Assigned(FOnWork)) and (Assigned(FJob)) then FOnWork(Self,FJob); sleep(1); end; end; |
Re: Selbstgebauter Threadpool funktioniert nicht
Häng bitte mal die Units an. So fehlt doch noch ziemlich viel Relevantes.
Warum bist du so ein Freund von Polling? Zumindest beim Threadpool ist eventbasiertes Arbeiten Pflicht. Bei den Sockets sehe ich auch keinen Grund dagegen. |
Re: Selbstgebauter Threadpool funktioniert nicht
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
Bin kein Freund von Polling :mrgreen: Aber ich weiß mir grad nicht anders zu helfen :? |
Re: Selbstgebauter Threadpool funktioniert nicht
Delphi-Quellcode:
So pollt wenigstens der Threadpool nicht mehr.
procedure TThreadPool.AddJob(AJob: TObject);
begin PostQueuedCompletionStatus(FIOComPort,1,Cardinal(AJob),nil); end; procedure TThreadPool.Dead; var i: Integer; begin for i:=1 to FThreads.Count do PostQueuedCompletionStatus(FIOComPort,0,0,nil); //"Beenden"-Nachricht schicken end; procedure TThreadPoolThread.GetJob; var bytes: Cardinal; over: POverlapped; AJob: Cardinal; begin if not GetQueuedCompletionStatus(FIOComPort,bytes,AJob,over,INFINITE) then //!! RaiseLastOsError; if bytes = 0 then Dead else FJob := TObject(AJob); end; procedure TThreadPoolThread.Execute; begin while True do begin GetJob; if FDead then Exit; if (Assigned(FOnWork)) and (Assigned(FJob)) then FOnWork(Self,FJob); end; end; Warum bist du so masochistisch, dich mit der Unit Sockets anzulegen? :mrgreen: Da bist du doch schneller, indem du direkt die Windows-Funktionen benutzt. Schau dir mal die Unit ScktComp an: Da wird gezeigt, wie man ohne zusätzliche Threads über die Winsockets kommunizieren kann. Da gibt es nämlich auch Möglichkeiten, ereignisgesteuert zu arbeiten. |
Re: Selbstgebauter Threadpool funktioniert nicht
Hi,
Danke schonmal für deine Verbesserungsvorschläge. Ich schau mir das gleich mal an. Wie ich gesehen hab, arbeiten die ScktComp Sockets mit WindowMessages. Habe vorher die ICS von Overbyte benutzt, die auch mit Messages gearbeitet hat und kam zu dem Schluss, dass "messagebasierte" Sockets für mein Vorhaben ungeeignet sind. Habe Testweise 200 Sockets auf meinen Server losgelassen (damals noch ICS). Wenn alle diese Sockets dem Server alle paar Millisekunden Daten geschickt hat und dann noch neue Clientverbindungen reinkamen, kamen von 200 neuen Verbindungen nur ca. 10 beim Server an. Ich gehe davon aus, dass es daran lag, dass Windows nichtmehr hinterhergekommen ist mit den Messages (o.ä.). Daher habe ich alternative Komponenten gesucht. Jedoch keine geeigneten gefunden und habe mich dann schließlich entschlossen mir eigene Sockets auf Basis der Sockets.pas zu bauen. Und bevor ich meinen Threadpool eingebaut hatte, war meine Socketklasse auch die für meinen Fall am besten funktionierendste. |
Re: Selbstgebauter Threadpool funktioniert nicht
Das ist aber kein Grund zu pollen. Es gibt bei den Winsockets zwei Möglichkeiten, ereignisgesteuert zu arbeiten, nämlich mit WSAAsyncSelect und WSAEventSelect. Wenn dabei bei einem Socket etwas anliegt, wird eine Nachricht geschickt bzw. ein Event gesetzt. Wenn dir die Methode mit den Nachrichten nicht schnell genug ist, erstelle dir für jedes Socket ein Event und verwende WSAEventSelect. Wenn du dann allerdings mehr als 64 Sockets hast, brauchst du einen weiteren Thread. Wenn einer dieser Threads dann feststellt, dass ein Ereignis eingetroffen ist, kann er den entsprechenden Job an den Threadpool weiterreichen. Das sollte nicht langsamer sein als die Methode mit dem Polling, aber bei geringer Last deutlich weniger CPU-Zeit verbrennen.
|
Re: Selbstgebauter Threadpool funktioniert nicht
Hi,
Ich kenne mich mit der SocketAPI nicht aus, aber ich werde mir das mal anschauen. Aber du meintest, dass ich für alle 64 Clients nen eigenen Thread brauche (wenn ich dich nicht falsch verstanden habe). Voraussichtlich werde ich bis zu 2000 Clients haben. Das wären 32 Threads (+ X für andere Aufgaben). Liegt das noch in einem akzeptablen Rahmen? |
Re: Selbstgebauter Threadpool funktioniert nicht
Zitat:
Aber (ohne dein Problem näher zu kennen), du könntest auch mal über mehrere Prozesse nachdenken. |
Re: Selbstgebauter Threadpool funktioniert nicht
Möglicherweise genügt es, wenn du einen eigenen Thread mit einer Nachrichtenschleife erstellst, ihm ein Fenster spendierst und bei diesem dann mit WSAAsyncSelect alle Sockets registrierst, das ist dann einfacher als mit den Events. Aber ganz ehrlich: Ich habe keine Ahnung, wie sich Windows bei so einer Belastung verhält. Versuche es.
|
Re: Selbstgebauter Threadpool funktioniert nicht
Naja ich befürchte zwar, dass ich nur belächelt werde, aber es geht mir (der ein oder andere erinnert sich vielleicht noch) um mein Online-RPG. Lange Zeit hat das Projekt geschlafen und im Dezember habe ich es nochmal von vorne begonnen.
Zur Zeit baue ich erstmal ein paar Serverprototypen und teste verschiedene Dinge, weil ich denke, dass eine funktionierende, gute asynchrone Server<->Client Kommunikation eines der wichtigsten aber auch schwersten Dinge werden wird. Habe es wie gesagt schon mit verschiedenen Serverstrukturen bzw Komponenten versucht. Entweder waren die Komponenten vom Aufbau her nicht für meine Pläne geeignet oder sie waren wie z.B. die ICS zu langsam, bzw. bei vielen Anfragen zu unzuverlässig. Dann begann ich damit mir auf Basis der Sockets eigene Socketklassen zu schreiben. Und an diesem Punkt bin ich eben jetzt gerade. Die Sockets, bzw mein Server soll eben mit bis zu 2000 Clients zurecht kommen. Das habe ich mir einfach mal als Ziel gesetzt. Wenn es ein paar weniger werden, dann ist das auch nicht tragisch. Aber es soll eben gut und zuverlässig funktionieren. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz