close Threadhandle
-
Was spricht dagegen sich eine Verwaltung über eine Map aufzubauen?
Die terminierenden Threads können sich ja selbst austragen, dann hast Du auch keine Unmemge Handles offen, die Du verwalten musst.
Dann hast Du immer eine Liste der eben gerade noch laufenden Threads.Du musst auch eine Liste der Threads haben, wie willst Du sonst den Threads mitteilen, das sie Schluß machen sollen.
-
Was nützt mir eine Liste der noch laufenden Threads? Bzw. anders gefragt: Wer schließt die Handles der beendeten Threads? Machen die Threads das selbst?
Falls ja, hätte doch eine Wait-Funktion keine gültigen Handles, auf die sie warten könnte, oder?
Beispiel:
Der Server soll beendet werden und es laufen noch 3 Threads, deren Handles in einem Array eingetragen sind.
WaitForMulitpleObjects wird aufgerufen - aber die Threads schließen ihr Handle beim Beenden.
Schlägt dann die Wait-Funktion nicht fehl?Den Vorschlag mit der Semaphore verstehe ich auch nicht, ich müsste ja am Ende warten, bis Initial-Count wieder gleich Max-Cout ist, aber wie soll ich das anstellen?
Den Threads soll übrigens nicht mitgeteilt werden, daß sie Schluß machen sollen (außer dem Listen-Thread), da sie eine genau definierte endliche Aufgabe bekommen, kommen sie von selbst zum Ende, und eben das soll abgewartet werden.
-
Was machst Du denn mit dem Handle von CreateThread/_beginthreadex?
Wenn Du es schließt, hast Du keine Handhabe mehr über den Thread.Stimmt! Das Handle muss noch gültig sein, um darauf zu warten. Ich mache mir da nie große Gedanken, weil ich eine Workerthread Basisklasse verwende, die sich etsprechend auch selbst verwaltet...
Ich denke, dass Du um eine grundsätzliche Verwaltung nicht drum herum kommst.
-
Belli schrieb:
Den Vorschlag mit der Semaphore verstehe ich auch nicht, ich müsste ja am Ende warten, bis Initial-Count wieder gleich Max-Cout ist, aber wie soll ich das anstellen?
Hallo, das brauchst Du nicht anstellen, das erledigt die Kernel automatisch.
Jedes ReleaseSemaphore incrementiert den Zähler der Semaphore.
-
Ich habe gerade folgende Idee:
Ich erstelle ein globales Event-Objekt.
Wenn ich einen neuen Client-Thread starte, inkrementiere ich einen globalen Zähler und resette das Event.
Die Threads starte ich mit _beginthread, so daß sie ihr Handle selbst schließen. Wenn ein Thread terminiert, dekrementiere ich den globalen Zähler und prüfe, ob er Null erreicht hat. Falls ja, setze ich das Event-Objekt auf signaled.Event- und Zählermanipulation/prüfung schütze ich durch eine Critical-Section.
Wenn der Server beendet werden soll, beende ich zuerst den Listen-Thread durch closesocket() und warte dann auf das Event-Objekt.
Das sollte ein gangbarer Weg sein, oder?
-
CStern schrieb:
Belli schrieb:
Den Vorschlag mit der Semaphore verstehe ich auch nicht, ich müsste ja am Ende warten, bis Initial-Count wieder gleich Max-Cout ist, aber wie soll ich das anstellen?
Hallo, das brauchst Du nicht anstellen, das erledigt die Kernel automatisch.
Jedes ReleaseSemaphore incrementiert den Zähler der Semaphore.Ja, schon klar, aber wie stell ich bei Programmende fest, ob alle Threads fertig sind, sprich, ob Initial-Count wieder gleich Max-Count ist?
Ich bräuchte praktisch eine Wait-Funktion, die wartet, bis der Ausgangsstatus wieder erreicht ist.
-
So etwas gibt es nicht. Du müsstest den Semaphore "leer lesen"...
Einen Semaphore halte ich nicht für eine gute Lösung. Man kann eben nicht gezielt die noch laufenden Threads beenden...
-
Belli schrieb:
CStern schrieb:
Belli schrieb:
Den Vorschlag mit der Semaphore verstehe ich auch nicht, ich müsste ja am Ende warten, bis Initial-Count wieder gleich Max-Cout ist, aber wie soll ich das anstellen?
Hallo, das brauchst Du nicht anstellen, das erledigt die Kernel automatisch.
Jedes ReleaseSemaphore incrementiert den Zähler der Semaphore.Ja, schon klar, aber wie stell ich bei Programmende fest, ob alle Threads fertig sind, sprich, ob Initial-Count wieder gleich Max-Count ist?
Ich bräuchte praktisch eine Wait-Funktion, die wartet, bis der Ausgangsstatus wieder erreicht ist.Im Thread: Wenn GetLastError() größer 0 ist. Im Initialthread, wenn das Semaphore signalisiert ist.
Ich habe aber nochmals darüber nachgedacht und bin zum Schluß gekommen, dass man eigentlich mit dem von mir vorgeschlagenen Konstrukt das nachbaut, was InterlockedDecrement und InterlockedIncrement auch zu bieten haben und zwar insbesondere dann, wenn man vom Initialthread aus auch auf die Threads zugreifen will.
Früher hatte ich die Threadhandles, wie hier auch schon vorgeschlagen wurde, in einer map gesammelt, deren Key Socket war. Das war richtig performant im Zusammenhang mit WSAAsyncselect, wobei ja der Socket in der Message direkt mitgeliefert wird. Allerdings erspart auch das nicht die Prüfung, ob der Handle zu dem Thread noch gültig ist, oder nicht.
Also: Vorschlag Semaphore -> R.i.P.
Allerdings bringt:
std::map<SOCKET,HANDLE> m_CLIENTS; HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AcceptThread, (void*)sAccept, 0, &nID); m_CLIENTS[sAccept] = hThread;nicht wenige Warnungen des Compilers auf den Plan, weswegen ich damals die Sache nicht weiter verfolgt habe (mangels Zeit. Vielleicht ist auch deswegen aus mir: Weiße Haut, keine Rothaut == Apache geworden
).P.S.: Der Apache-Server wurde deshalb so erfolgreich, weil er eine ziemlich intelligente Threadverwaltung hat. Soundsoviel Threads erzeugen eine neue Instanz des Process und hier wieder können mehrere Threads verwaltet werden. Aber das dürfte Multiprozessor-Studie sein. Wir bleiben auf dem Teppich

-
CStern schrieb:
Belli schrieb:
CStern schrieb:
Belli schrieb:
Den Vorschlag mit der Semaphore verstehe ich auch nicht, ich müsste ja am Ende warten, bis Initial-Count wieder gleich Max-Cout ist, aber wie soll ich das anstellen?
Hallo, das brauchst Du nicht anstellen, das erledigt die Kernel automatisch.
Jedes ReleaseSemaphore incrementiert den Zähler der Semaphore.Ja, schon klar, aber wie stell ich bei Programmende fest, ob alle Threads fertig sind, sprich, ob Initial-Count wieder gleich Max-Count ist?
Ich bräuchte praktisch eine Wait-Funktion, die wartet, bis der Ausgangsstatus wieder erreicht ist.Im Thread: Wenn GetLastError() größer 0 ist. Im Initialthread, wenn das Semaphore signalisiert ist.
Also nach dem, was ich über Semaphore nachgelesen habe, ist sie immer signalisiert, solange sie nicht auf 0 runtergezählt ist ...
Was ist mit meiner Idee mit dem Event?
-
Wenn du alles korrekt implementierst (z.b. sicherstellst dass ein Thread nicht terminieren kann ohne dass der entsprechende exit-code ausgeführt wird), und alle potentiellen Race-Conditions "umschiffst", dann müsste das schon gehen.
Ich empfehle dir aber zu diesem Zwecke zumindest eine CRITICAL_SECTION + einen Event zu verwenden.