@Olli:
Zitat:
Ich stimme soweit Hagens Schilderung zu, möchte aber noch darauf hinweisen, daß man unter Windows ohnehin nicht sagen kann, ob die Wartezeit nun 250ms ist. Es handelt sich eben um kein Echtzeitbetriebssystem. Was man sagen kann ist: in beiden Fällen (WaitFor*Object(s), Sleep) wird Rechenzeit abgegeben und irgendwann nach mindestens der Wartezeit wird der Thread-Scheduler den Thread wieder an die Reihe nehmen. Das hängt aber von diversen Faktoren ab und ist nicht steuerbar.
Das stimmt, aber im Grunde wollte ich auf was anderes hinaus.
Denn mit der Anwendung von Sleep(250) ist es garantiert das druchschnittlich gesehen der Thread immer 125ms zu spät auf Daten im Socket reagiert, wenn der Socket auch welche empfangen hat. Das ist klassisches intervallgesteuertes Polling und fast genauso ineffizient wie ein direktes Polling ohne Sleep() in einer Threadschleife.
Mit Hilfe der Events und dem Tasksheduler stellt Windows quasi eine zeitlich saubere Synchronisation und Verteilung der Rechnerresourcen sicher. (ja nur unter normalen Umständen wir kennen das ja alle
)
1.) wird man dann nur den Socket lesen wenn auch wirklich Daten eingegangen sind und nicht alle 250ms sinnlos pollen
2.) ist die Reaktionszeit bis der Thread den Socket ausliest immer identisch und auf jeden Falle keine 125ms, die zeitlichen Verschiebungen bis ein Thread auf ein signalisertes Event reagieren kann liegt nur im Tasksheduler begründet und kann fast schon vernachlässigt werden.
Vielleicht ein Beispiel:
Das Nachschauen ob in einem Socket Daten vorliegen dauert 10 ms.
Der Server schickt seine Daten erst nach 1000ms an den Client.
Wir haben nun Methode 1. den Thread der 250ms per Sleep wartet und danach einfach testet ob Daten im Socket liegen.
Dieser Thread wird also exakt 4 mal Sleep(250ms) aufrufen und 3 mal wird er den Socket sinnlos pollen da noch keine Daten vorhanden sind. Macht also 4 * 250 + 3 * 10 ms = 1030ms minimal an Zeit. Dabei wird der Thread aber auch 4 mal einen Taskswitch miterleben was auch Zeit kostet. Im ungünstigesten Falle könnte es aber auch sein das just in dem Moment wo der Thread Sleep(250) aufruft Daten im Socket landen. Ergo der Thread wartet nochmals zusätzliche 250ms sinnlos und liest erst danach den Socket aus. Im Worstcase ergibt sich also 1280ms.
Nun Method 2 per Events.
Der Thread liest den Socket per Overlapped IO aus. Er ruft also Socket_Read() auf und diese Funktion kehrt sofort zum Thread zurück. Nun wartet der Thread per WaitForSingleObject() das Socket_Read() X Bytes an Daten empfangen hat. Das dauert also exakt 1000ms weil ja der Server diese Zeit benötigt. In dieser Zeit schläft der Thread, er wird also das System nicht weiter belasten. Fazit: 1000ms wartezeit ohne das System weiter zu belasten.
Gut, diese 30ms weniger scheinen im ersten Moment nicht viel aber jetzt wollen wir das dieser Thread gleichzeitig von 3 Servern Daten abholen soll. Und diese 3 Server haben unterschiedliche Antwortzeiten.
Sagen wir mal 1000ms, 1500ms und 1750ms.
Der Thread nach 1. Methode wird erstmal auf Server 1 warten, macht 1000ms dann auf Server 2 macht + 1500ms und dann Server 3 + 1750ms, summa summarum also 4250ms.
In der Methode 2. wird er alle 3 Server ansprechen und dann auf alle 3 Events der Sockets warten. Nach 1000ms antwortet der Server 1 und er Thread liest dessen Daten. Nach weiteren +500ms antwortet schon Server 2 und nach weiteren 250 ms der Server 3. Logisch 1000ms + 500ms = 1500ms + 250ms = 1750ms. Also schon anch 1750ms hat der Thread alle Daten der 3 Server abgearbeitet. Gut, man könnte auch 3 Threads erzeugen die separat warten, aber wozu wenn es auch so geht ?
Gruß Hagen