Thread Management



  • Da bin ich mal auf die Antwort von hustbaer gespannt. Der kennt sich damit aus!



  • Wenn der Main-Thread endet, enden alle Threads.



  • lies mal hier: http://www.c-plusplus.net/forum/p1741170

    Es gibt aber auch Prozesse ohnen primären Thread... bzw. der primäre Thread hat sich schon längst wieder beendet...



  • spike1993 schrieb:

    ja schon klar das erstellen des threads ist ja kein problem nur das beenden per dwThreadId

    Das ist klar dass das ein Problem ist. Threads beendet man ja auch nicht "per dwThreadId". Ein Thread beendet wenn die ThreadProc returned.



  • 314159265358979 schrieb:

    Wenn der Main-Thread endet, enden alle Threads.

    Das ist eine Designfrage des Betriebssystems. Unter Windows z.B. endet ein Prozess erst wenn der letzte Thread des Prozesses endet.



  • Naja,..

    so ganz stimmt diese aussage nicht. Der prozess ist unter windows beendet,
    wenn der letzte mit diesem Prozess assoziierte Thread beendet ist.

    Du kannst ja auch einen Thread erstellen, und das letzte Handle von diesem
    schließen. der Thread ist dann nicht mehr mit diesem Prozess assoziiert, läuft
    aber noch!



  • dot schrieb:

    314159265358979 schrieb:

    Wenn der Main-Thread endet, enden alle Threads.

    Das ist eine Designfrage des Betriebssystems. Unter Windows z.B. endet ein Prozess erst wenn der letzte Thread des Prozesses endet.

    Nein. Unter Windows ist das genau nicht so.



  • 314159265358979 schrieb:

    dot schrieb:

    314159265358979 schrieb:

    Wenn der Main-Thread endet, enden alle Threads.

    Das ist eine Designfrage des Betriebssystems. Unter Windows z.B. endet ein Prozess erst wenn der letzte Thread des Prozesses endet.

    Nein. Unter Windows ist das genau nicht so.

    Du hast unrecht!
    http://msdn.microsoft.com/en-us/library/ms686722(v=vs.85).aspx



  • falsch schrieb:

    314159265358979 schrieb:

    dot schrieb:

    314159265358979 schrieb:

    Wenn der Main-Thread endet, enden alle Threads.

    Das ist eine Designfrage des Betriebssystems. Unter Windows z.B. endet ein Prozess erst wenn der letzte Thread des Prozesses endet.

    Nein. Unter Windows ist das genau nicht so.

    Du hast unrecht!
    http://msdn.microsoft.com/en-us/library/ms686722(v=vs.85).aspx

    Probiers doch aus, du wirst feststellen, dass dem so ist. Sowohl mit pthreads, als auch mit boost.



  • Ja weil die CRT ExitProcess aufruft. Das ändert aber nichts daran das deine Aussage falsch ist.



  • Welche CRT? 😃



  • 314159265358979 schrieb:

    Nein. Unter Windows ist das genau nicht so.

    Doch, siehe Link vom Vorposter.

    zeusosc schrieb:

    Du kannst ja auch einen Thread erstellen, und das letzte Handle von diesem schließen. der Thread ist dann nicht mehr mit diesem Prozess assoziiert, läuft aber noch!

    Woher hast du das denn? Das kann eigentlich nur Blödsinn sein, würde das gehen so würde das bedeuten man kann Threads ohne Kontext erschaffen was a) komplett sinnlos wäre und b) zwangsweise crashen würde.



  • 314159265358979 schrieb:

    Welche CRT? 😃

    Hast du den Link auch nur kurz überflogen?



  • Der von "falsch" gepostete Link sollte eigentlich alles klären.

    Unter Windows endet ein Prozess, wenn alle seine Threads beendet wurden.



  • Bei mir hat der Prozess immer geendet, wenn der MainThread beendet wurde. Discuss!



  • Also wenn ich das MSDN Beispiel so änder, dass die Threads ewig laufen, wird das Programm trotzdem sofort beim return (Zeile 72) aus main beenden, auch wenn ich die anderen Threads nicht beende.

    #include <windows.h>
    #include <tchar.h>
    #include <strsafe.h>
    
    #define MAX_THREADS 3
    #define BUF_SIZE 255
    
    DWORD WINAPI MyThreadFunction( LPVOID lpParam );
    void ErrorHandler(LPTSTR lpszFunction);
    
    // Sample custom data structure for threads to use.
    // This is passed by void pointer so it can be any data type
    // that can be passed using a single void pointer (LPVOID).
    typedef struct MyData {
        int val1;
        int val2;
    } MYDATA, *PMYDATA;
    
    int _tmain()
    {
        PMYDATA pDataArray[MAX_THREADS];
        DWORD   dwThreadIdArray[MAX_THREADS];
        HANDLE  hThreadArray[MAX_THREADS]; 
    
        // Create MAX_THREADS worker threads.
    
        for( int i=0; i<MAX_THREADS; i++ )
        {
            // Allocate memory for thread data.
    
            pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
                    sizeof(MYDATA));
    
            if( pDataArray[i] == NULL )
            {
               // If the array allocation fails, the system is out of memory
               // so there is no point in trying to print an error message.
               // Just terminate execution.
                ExitProcess(2);
            }
    
            // Generate unique data for each thread to work with.
    
            pDataArray[i]->val1 = i;
            pDataArray[i]->val2 = i+100;
    
            // Create the thread to begin execution on its own.
    
            hThreadArray[i] = CreateThread( 
                NULL,                   // default security attributes
                0,                      // use default stack size  
                MyThreadFunction,       // thread function name
                pDataArray[i],          // argument to thread function 
                0,                      // use default creation flags 
                &dwThreadIdArray[i]);   // returns the thread identifier 
    
            // Check the return value for success.
            // If CreateThread fails, terminate execution. 
            // This will automatically clean up threads and memory. 
    
            if (hThreadArray[i] == NULL) 
            {
               ErrorHandler(TEXT("CreateThread"));
               ExitProcess(3);
            }
        } // End of main thread creation loop.
    
        // Wait until all threads have terminated.
    
        return 0;
        WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
    
        // Close all thread handles and free memory allocations.
    
        for(int i=0; i<MAX_THREADS; i++)
        {
            CloseHandle(hThreadArray[i]);
            if(pDataArray[i] != NULL)
            {
                HeapFree(GetProcessHeap(), 0, pDataArray[i]);
                pDataArray[i] = NULL;    // Ensure address is not reused.
            }
        }
    
        return 0;
    }
    
    DWORD WINAPI MyThreadFunction( LPVOID lpParam ) 
    { 
        HANDLE hStdout;
        PMYDATA pDataArray;
    
        TCHAR msgBuf[BUF_SIZE];
        size_t cchStringSize;
        DWORD dwChars;
    
        // Make sure there is a console to receive output results. 
    
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
        if( hStdout == INVALID_HANDLE_VALUE )
            return 1;
    
        // Cast the parameter to the correct data type.
        // The pointer is known to be valid because 
        // it was checked for NULL before the thread was created.
    
        pDataArray = (PMYDATA)lpParam;
    
        // Print the parameter values using thread-safe functions.
    
    	while(true)
    	{
    		StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"), 
    			pDataArray->val1, pDataArray->val2); 
    		StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
    		WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
    		Sleep(500);
    	}
        return 0; 
    } 
    
    void ErrorHandler(LPTSTR lpszFunction) 
    { 
        // Retrieve the system error message for the last-error code.
    
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
        DWORD dw = GetLastError(); 
    
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | 
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dw,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf,
            0, NULL );
    
        // Display the error message.
    
        lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
            (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR)); 
        StringCchPrintf((LPTSTR)lpDisplayBuf, 
            LocalSize(lpDisplayBuf) / sizeof(TCHAR),
            TEXT("%s failed with error %d: %s"), 
            lpszFunction, dw, lpMsgBuf); 
        MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK); 
    
        // Free error-handling buffer allocations.
    
        LocalFree(lpMsgBuf);
        LocalFree(lpDisplayBuf);
    }
    


  • Wie ich sagte :p



  • Weil der Code innerhalb der Laufzeitbibliothek vereinfacht so aussieht:

    void mainCRTStartup()
    {
        int ret = main(...);
        ExitProcess(ret);
    }
    

    Ohne den Aufruf von ExitProcesss würde der Prozess (unter Windows) weiterlaufen.



  • Welche Laufzeitbibliothek verdammt nochmal -.-
    Bei MinGW exakt selbes verhalten.



  • Ihr habt also quasi recht wenn ihr sagt "unter C++ ist das so".

    Aber das ist nicht das Verhalten des Betriebssystems.


Anmelden zum Antworten