Einen Thread erneut verwenden!



  • Ich hab ein Problem und zwar sitze ich gerade daran einen HTTP Server in "C" zu programmieren und da stellt sich natürlich früher oder später die aufgabe des Multithreadings mit Hilfe eines Threadpools. Genau an diesem Punkt bin ich nun auch angekommen und es stellt sich folgendes Problem:

    Die 10 Threads erstelle ich am Anfang als CREATE_SUSPEND und beim ersten aufruf für jeden der zehn Threads aktiviere ich diesen mit ResumeThread und schläfer ihn am Ende wieder mit SuspendThread ein. Das Problem ist nun jedoch, wenn jeder der zehn Threads einmal etwas zu tun hatte und somit schonmal durch ResumeThread aktiviert und durch SuspendThread wieder schlafen gelegt wurde, bleibt mein Server hengen und reagiert nicht mehr! Ich kann also einen Thread nicht mehrmals verwenden.

    Meine idee ist, dass ich einen Threadpool habe, den ich mit hilfe einer struktur aufbaue(linked list) und halt immer den ersten Thread benutze und ihn dann aus der linked list herausnehme! Wenn keine Threads mehr vorhanden sind, weil alle gerade verwendet werden, wird 30 sec gewartet.

    ich hoffe es kann mir jemand weiterhelfen, bin schon ziemlich am verzweifeln!

    Danke schonmal!

    Hier ein bißchen Quellcode, falls noch andere Teile oder alles benötigt wird einfach bescheid sagen!

    struct vom Threadpool:

    typedef struct THREADPOOL_s
    {
    	LPDWORD wThreadID;
    	CRITICAL_SECTION csectionAccept;
    	HANDLE hThread;
    
    	SOCKET sdAccept;
    	fd_set rfds;
    	bool bStopRunning;
    
    	MYSQL *pMySQL; //!
    
    	THREADPOOL_s *pThreadNext;
    }
    THREADPOOL_t;
    

    init ThreadPool:

    pStart_T = (THREADPOOL_t*) malloc(sizeof(THREADPOOL_t));
    
    	if (pStart_T == NULL)
    		return -1;
    
    	memset(pStart_T, 0, sizeof(THREADPOOL_t));
    
    	pStart_T->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnThreadMessage, pStart_T, CREATE_SUSPENDED, pStart_T->wThreadID);
    
    	if (pStart_T->hThread == NULL)
    	{
    		printf("errorcode: %d\n", GetLastError());
    		cleanup(pStart_M, NULL);
    		free(pStart_T);
    		printf("Cannot create Thread!\n");
    		return -1;
    	}
    
    	pTmp_T = pStart_T;
    
    	for (i = 0; i < 10; i++)
    	{
    
    		pNew_T = (THREADPOOL_t *)malloc(sizeof(THREADPOOL_t));
    
    		if (pNew_T == NULL)
    		{
    			cleanup(pStart_M, pStart_T);
    			return -1;
    		}
    
    		memset(pNew_T, 0, sizeof(THREADPOOL_t));
    
    		pNew_T->hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfnThreadMessage, pNew_T, CREATE_SUSPENDED, pNew_T->wThreadID);
    
    		if (pNew_T->hThread == NULL)
    		{
    			cleanup(pNew_M, pNew_T);
    			printf("Cannot create Thread!\n");
    			return -1;
    		}
    
    		pTmp_T->pThreadNext = pNew_T;
    		pTmp_T = pNew_T;
    	}
    

    benutzen des Threads:

    do
    	{
    		if (listen(sdListen, MAX_SERVER_CONNECTIONS) == -1)
    		{
    			printf("Error listen()\r\n");
    			continue;
    		}
    
    		pThread = allocThreads();
    
    		if (pThread->hThread == NULL)
    		{
    			//deleteMessage(pThread);
    			free(pThread);
    			printf("No Threads are available!\n");
    		}
    		else
    		{
    			pThread->sdAccept = accept(sdListen, NULL, NULL);
    
    			if (pThread->sdAccept == -1)
    			{
    				releaseThread(pThread);
    				printf("connection failed! socket\r\n");
    				continue;
    			}
    
    			dwRet = ResumeThread(pThread->hThread);
    
    			if (dwRet == -1)
    			{
    				printf("errorcode: %d\n", GetLastError());
    				//deleteMessage(pThread);
    				free(pThread);
    				printf("Cannot resume Thread!\n");
    				releaseThread(pThread);
    			}
    		}
    }
    	while (1);
    

    alloc thread funktion:

    static THREADPOOL_t* allocThreads()
    {
    	THREADPOOL_t *pActive, *pTMP;
    
    	mutexlock(true);
    	pTMP = pFirst_T;
    
    	if (pTMP != NULL)
    	{
    		pActive = pTMP;
    		pFirst_T = pTMP->pThreadNext;
    
    		mutexlock(false);
    
    		return pActive;
    	}
    	else
    	{
    		mutexlock(false);
    		return NULL;
    	}
    }
    

    thread hat seine aufgabe erledigt:

    if (recvCommand(pThread) == 0)
    	{
    		iMySQLControl = 0;
    
    		if (shutdown(pThread->sdAccept, 0) != 0)
    			printf("shutdown-error(M)!\r\n");
    
    		closesocket(pThread->sdAccept);
    		killmutex(pThread);
    		//deleteMessage(pThread);
    		//free(pThread);
    		printf("Connection: closed\r\n\r\n\r\n");
    		releaseThread(pThread);
    
    		return (void *) -1;
    	}
    

    zu guter letzt die release Thread Funktion:

    void releaseThread(THREADPOOL_t *pThread)
    {
    	THREADPOOL_t *pTMP;
    	DWORD dwRet;
    
    	mutexlock(true);
    
    	if (pFirst_T != NULL)
    	{
    		pTMP = pFirst_T;
    
    		while (pTMP->pThreadNext != NULL)
    			pTMP = pTMP->pThreadNext;
    
    		pTMP->pThreadNext = pThread;
    		pTMP->pThreadNext->pThreadNext = NULL;
    	}
    	else
    	{
    		pFirst_T = pThread;
    		pFirst_T->pThreadNext = NULL;
    	}
    
    	mutexlock(false);
    	dwRet = SuspendThread(pThread->hThread);
    
    	if (dwRet == -1)
    	{
    		printf("errorcode: %d\n", GetLastError());
    		exit(0);
    	}
    }
    


  • Ohne viel gelesen zu haben:
    Falsche herangehensweiße. SuspendThread ist gedacht für Debugger.



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum ANSI C in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.


  • Mod



  • ok...dann werde ich das wohl anders machen müssen. gibt es denn eine möglichkeit das grundprinzip umzusetzen, dass ich beim start des servers die 10 threads erstelle und sie dann nachher immer verwende und wieder weglege(pausieren, oder was auch immer), halt nur nicht mit suspend thread dann?


  • Mod

    Nimm doch ein Event für jeden Thread, das signalisiert, dass neue Arbeit vorhanden ist.



  • ok das hört sich interessant an! kannst du mir vielleicht auch ein bißchen beschreiben, wie ich das genau machen kann? msdn hilft mir dabei irgendwie nicht so wirklich weiter..was aber auch daran liegen könnte, dass ich noch ziemlicher anfänger bin! 😉 Ausbildung läuft erst ein 3/4 jahr!

    danke für die reichlichen antworten!

    Für konkrete Beispiele bin ich immer empfangsbereit! 😃



  • guck nach
    CreateEvent //machst en event am besten für jeden deiner threads einen
    SetEvent //setzt ein event im main thread
    WaitForSingleObject //lässt deinen thread warten bis das event mit SetEvent gesetzt wurde

    Is ganz einfach guck mal danach inner msdn sind genug beispiele


Log in to reply