paddy_de Geschrieben 8. März 2010 Geschrieben 8. März 2010 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 noch ein bissl Sourcecode: 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); } } Zitieren
Klotzkopp Geschrieben 8. März 2010 Geschrieben 8. März 2010 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 ist eine ganz schlechte Idee. Siehe die Hinweise in der MSDN Library zu SuspendThread. Diese Funktionen sind eigentlich nur für Debugger gedacht. Wenn du einen Thread in dem Moment schlafen legst, wenn er gerade ein Lock auf eine Ressource des Betriebssystems hat, kann dein ganzes Programm hängenbleiben. Zitieren
paddy_de Geschrieben 9. März 2010 Autor Geschrieben 9. März 2010 Das ist eine ganz schlechte Idee. Siehe die Hinweise in der MSDN Library zu SuspendThread. Diese Funktionen sind eigentlich nur für Debugger gedacht. Wenn du einen Thread in dem Moment schlafen legst, wenn er gerade ein Lock auf eine Ressource des Betriebssystems hat, kann dein ganzes Programm hängenbleiben. Das hab ich gelesen ja und ich weiß auch, dass das nicht zu empfehlen ist es so zu machen. Mein chef möchte das aber gerne und daher suche ich nach einer lösung das trotzdem so zu machen. nur so langsam bin ich am verzweifeln, da ich keine geeignete lösung finde...! Zitieren
Klotzkopp Geschrieben 9. März 2010 Geschrieben 9. März 2010 Das hab ich gelesen ja und ich weiß auch, dass das nicht zu empfehlen ist es so zu machen. Es ist nicht "nicht zu empfehlen". Es ist für das, was du vorhast, komplett ungeeignet. Why you should never call Suspend/TerminateThread (Part I) - Jochen Kalmbach's WebLog Why you should never call Suspend/TerminateThread (Part II) - Jochen Kalmbach's WebLog Mein chef möchte das aber gerne und daher suche ich nach einer lösung das trotzdem so zu machen.Dann wirst du deinem Chef klarmachen müssen, dass das so nicht geht. Zitieren
paddy_de Geschrieben 10. März 2010 Autor Geschrieben 10. März 2010 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? Zitieren
Klotzkopp Geschrieben 10. März 2010 Geschrieben 10. März 2010 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? Benutz die üblichen Synchronisationsobjekte: Events, Mutexe, Semaphoren oder Critical Sections, die sind für so etwas gedacht. Zitieren
paddy_de Geschrieben 10. März 2010 Autor Geschrieben 10. März 2010 ok das hab ich mir schon gedacht...hab mir das auch alles schon durchgelesen, aber so wirklich weit bin ich damit noch nicht gekommen! naja aber danke auf jeden fall dür die schnelle Hilfe! ich werd mir dann wohl noch ein paar tage den kopf darüber zerbrechen! Hat vll schonmal jemand sowas ähnliches gemacht und kann mir ein bißchen beispielcode schicken oder so? Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.