Fragen zum richtigen Umgang mit Threads



  • Ok, ich erkläre es mal im Groben. Mein Programm scannt Spiele Server. Eine vorgegebene List mit einer variablen Anzahl von IP Adressen (z.Z. bis zu 20480) wird der Reihe nach gescannt und die Informationen grafisch aufgearbeitet. Ich habe die ganze Zeit die Threads über einen „Masterthread“ so gestartet:

    //ScanThread zig mal gestartet
    void Query_Server(int server_id){
    	:
    	:
    	EnterCriticalSection(&myCriticalSection);
    //	Kritischer Code!!!!!!!!!!!!!!!!!!!!!!!
    	LeaveCriticalSection(&myCriticalSection);
    :
    	:
    	ExitThread(0);
    }
    
    //HauptThread 1x gestartet
    void myFunction(void){
    
    	HANDLE	myThread;
    	DWORD		myThread_ID;
    	:	
    	:
    	:
    	:
    	for (server_id = 0; server_id < MAX_SERVER; server_id++){
    		MyThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Query_Server, (void *)server_id, 0, &MyThread_ID);
    		if(MyThread){
    			CloseHandle(MyThread);
    	}
    	Sleep(1000/server_per_second);
    	ExitThread(0);
    }
    

    Ähm, ich sollte dazusagen, daß das Programm soweit gut läuft, nur wenn es während der Scanphase mit ALT+F4 oder über das Menü beendet wird, kann es zu Überschneidungen kommen, weil schon Daten gesichert werden, aber irgendwelche Nachzügler Threads noch Daten schicken dann crasht mein Programm. Ich denke ich sollte an dieser Stelle überprüfen, welche Threads noch aktiv sind und erst mit der Sicherung der Daten anfangen, wenn auch der letzte der gestarteten Threads sich beendet hat. Ja das ist dann das Problem das ich habe, wie gehe ich da am geschicktesten dran.



  • indem du z.B. in deinen Thread (in denen du vermutlich auch zyklische abfragen hast) auch bei jedem zyklus darauf wartest das ein abbruchsignal kommt ... und vor verlassen des thread eine dem thread zugeordnete variable veränderst .... was weis ich, eine finished variable z.B. die der Thread kurz vorm beenden auf true setzt ... im main wartest du halt nur ab das alle variablen auf true sind ..... stichwort EVENT an dieser stelle, macht dads ganze vll. noch ansehnlicher


  • Mod

    Vermeide CreateThread, wenn Du CRT Funktionen verwendest. Das erzeugt Leaks in der CRT.
    Verwende immer _beginthread(ex)



  • @Ceos, ja das mit der Variablen hab ich mir auch schon so gedacht, jetzt weis ich nicht wie es sich verhält, wenn sich ein Thread mal verabschiedet, und die Var dann immer noch gesetzt ist, da müsste dann halt ein Timer die Sache beenden.

    @Martin, das mit der Verwendung von "_beginthread(ex)" hab ich auch mal in der MSDN Docu entdeckt, kannst du mir sagen was CRT Funktionen sind?



  • Das sind die C-Runtime-Library-Funktionen, also alles, was der C-Standard umfaßt.



  • Das heist also, wenn ich im meinem Thread strcpy, sprintf oder dergleichen verwende sollte ich den Threat mit "_beginthread(ex)", wenn ja nach welche Kriterein benutze ich dann um "_beginthread" oder aber "_beginthreadex" zum Starten zu verwenden?


  • Mod

    • Holgi * schrieb:

    Das heist also, wenn ich im meinem Thread strcpy, sprintf oder dergleichen verwende sollte ich den Threat mit "_beginthread(ex)",

    Ja!

    wenn ja nach welche Kriterein benutze ich dann um "_beginthread" oder aber "_beginthreadex" zum Starten zu verwenden?

    Ich verstehe Deine Frage nicht. Die Frage ist was Du benötigst. _beginthreadex benötigst Du z.B. um einen Thread suspended zu erzeugen...



  • wenn sich ein Thread mal verabschiedet

    musst du deinen code halt doppelt und 3 fach absicher so mit try catch usw. ansonsten fällt mir da adhoc nur noch ein das du regelmäig einer variable einen zeitwert übergibst, den du auf 0 setzt wenn der thread beendet ... ansonsten möglichst regelmäßig updaten und den thread abschiessen wenn er 5 sek nicht reagiert .... dabei musst du aber beachten das z.B. das connect nicht zu lange dauert (non blocking mode benutzen kann da abhilfe schaffen)



  • Übrigens erhält jeder erzeugte Thread einen Stack.
    Die Grösse kann bei CreateThread (und auch bei beginthread..) angegeben werden.
    Wird 0 angegeben (wie bei Dir) wird der Stack auf 1MB festgelegt.

    Das sind bei 200 Threads alleine wegen den Thread Stacks schon 200MB die reserviert sind.

    Ich halte soviele Threads nicht für sinnvoll (nur schon wegen den Context Switches und dem Memory Verbrauch).

    Für IO gibt es mehrere Lösungen, wie man mit deutlich weniger Threads auskommt (Overlapped IO, APC, IO Completion Ports).

    Grüsse
    Simon



  • Ja, da hast du bestimmt Recht. Ich werde nachdem ich dieses Problem hier gelöst habe, versuchen alternative einen anderen Weg einschlagen und damit den Serverscan zu realisieren. Leider bin ich auf den Gebieten wie du sie anspricht überhaut nicht bewandert und so werde ich wohl noch einige Zeit brauchen bis ich mich einigermassen in der Materien auskenne. Also danke erstmal für die Antworten und Denkanstösse.



  • Speicherverbrauch ist normal kein Problem bei 200 Threads, und Context-Switches tun auch nicht wirklich soviel teurer als Dispatching über IO Completion Ports o.Ä.

    Bei 1000-10.000 Connections sieht die Sache allerdings schonwieder ganz anders aus - das bekommt man mit Threads (1 Thread pro Connection meine ich) kaum noch irgendwie hin.



  • stichwort select(...) und dann die ankommenden daten nacheinander verarbeiten (evtl. ne datenstruktur in einer map<SOCKET,MyServerData> speichern) brauch nur einen thread ... blöd natürlich wenn du 10000 sockets hast und die zeitkritisch reagieren sollen ...



  • So und jetzt hab ich doch noch eine Frage, und zwar mein Controll thread der die anderen threads kontrolliert, ob sie noch laufen, ob die maximalzahl gestarted ist, etc. Wie kann ich es anstellen das dieser Thread eine höhere Priorität oder mehr cpu Zeit wie immer man dazu sagt. Also ich weiss noch nicht ob ich das überhaupt benötige, aber zu wissen was geht und was nicht wäre schon mal hilfreich.



  • Bissi MSDN Lesen schadet nicht:

    // in dem Thread der die höhere Priorität bekommen soll:
    ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
    

Anmelden zum Antworten