CriticalSection in Threads



  • Microsoft Visual Studio Version 2005
    Version 8.0.50727.42

    Installiert ist: Microsoft Visual C++ 2005

    Ja wirklich seh interresant, ich wunder mich halt schon vor allem weil der code genau so in den unterlagen steht. Hab auch schon viele andere Kombinationen probiert, brachte aber immer einen Fehler



  • Was bricht wo bei Dir?



  • Er gibt ein paar Zahlen aus, dann schlägt der Just-in-time-Debugger zu. Sprich während der Laufzeit bricht er ab.



  • Ändere '<= 5' in '< 5' damit der Code richtig ist, dann geht er auch.
    So wie du es machst überschreibst du evtl. (je nach Compiler) einen Teil der CRITICAL_SECTION beim Zugriff auf das nicht vorhandene Element mit Index 5 (=das 6. Element).

    EDIT: und ja, du solltest _beginthreadex verwenden statt CreateThread. Und die Stacksize mit 0 ist schon OK, 0 an der Stelle heisst einfach "Defaultwert bitte".



  • Laines schrieb:

    Er gibt ein paar Zahlen aus, dann schlägt der Just-in-time-Debugger zu. Sprich während der Laufzeit bricht er ab.

    Joh, jetzt seh ich es auch 😉



  • Hi danke für die Hilfe! Jetzt funktioniert es... 😃

    Als Ausgabe bekomme ich jetzt:

    325160
    325160
    325160
    325160
    325160
    972815
    972815
    972815
    972815
    972815
    1612520
    1612520
    1612520
    1612520
    1612520
    2257895
    2257895
    2257895
    2257895
    2257895
    2886293
    2886293
    2886293
    2886293
    2886293
    3514801
    3514801
    3514801
    3514801
    3514801
    4119651
    4119651
    4119651
    4119651
    4119651
    4758877
    4758877
    4758877
    4758877
    4758877
    5403220
    5403220
    5403220
    5403220
    5403220
    6055197
    6055197
    6055197
    6055197
    6055197
    6697034
    6697034
    6697034
    6697034
    6697034
    7343790
    7343790
    7343790
    7343790
    7343790
    7974854
    7974854
    7974854
    7974854
    7974854

    Sollte da jetzt nicht aber sowas stehen:

    111111
    222222
    333333
    444444
    444444 --> Wiederholungen könnten ja vorkommen mangels synchronisation
    555555

    Ich muss mir CreateThread arbeiten ist in der Aufgabe gefordert.



  • hustbaer schrieb:

    Ändere '<= 5' in '< 5' damit der Code richtig ist, dann geht er auch.

    Da bin ich ja voll auf den Leim getrampelt... 🙂

    hustbaer schrieb:

    So wie du es machst überschreibst du evtl. (je nach Compiler) einen Teil der CRITICAL_SECTION beim Zugriff auf das nicht vorhandene Element mit Index 5 (=das 6. Element).

    EDIT: und ja, du solltest _beginthreadex verwenden statt CreateThread. Und die Stacksize mit 0 ist schon OK, 0 an der Stelle heisst einfach "Defaultwert bitte".

    Dabei hatte ich solch einen "schönen" RT-Fehler beim "Clonen" des Stacks vermutet.

    Wie war das "KISS" oder so ähnlich... 😃



  • Ich hab's auch erst beim Durchsteppen gesehen 😉

    @Laines: der Output ist doch eh korrekt. Dadurch dass du keine Pause zwischen "unlock" und "lock" hast wird es ziemlich unvorhersehbar wann der Besitzer der CRITICAL_SECTION wechselt.
    Wenn du das synchronisieren willst so dass erst Thread1 einmal drankommt zum Zählen, dann Thread2 einmal zum ausgeben, dann wieder 1 etc. - dann musst du EVENTs oder schlimmeres verwenden 😉



  • Hier erstmal der Code wie weit er jetzt ist:

    #include <iostream>
    #include <windows.h>
    #include <conio.h>
    #include <process.h>
    #include <stdio.h>
    
    using namespace std;
    
    // Gemeinsamme struktur
    struct gemeinsamme_daten{
    	int array[5];
    };
    
    // Object von Gemeinsamer Struktur
     gemeinsamme_daten daten;
    
    // Erstellen der Critical section
     CRITICAL_SECTION cs;
    
    // Event erzeugen
     HANDLE hEvent = CreateEvent( 
            NULL,         // default security attributes
            TRUE,         // manual-reset event
            FALSE,         // initial state is non signaled
            "Event"  // object name
            ); 
    
    // Funktion zum ersten Thread
    DWORD WINAPI ThreadProc1(LPVOID lpParam){
    	gemeinsamme_daten *p = (gemeinsamme_daten*) lpParam;
    	int i(0);
    	while(true){
    	EnterCriticalSection(&cs);
    		for(int y(0); y < 5; y++){
    		p->array[y] = i;
    		}
    	i++;
    	LeaveCriticalSection(&cs);
    	}
    return 0;
    }
    
    // Funktion zum zweiten Thread
    DWORD WINAPI ThreadProc2(LPVOID lpParam){
    	gemeinsamme_daten *p = (gemeinsamme_daten*) lpParam;
    	int i(0);	
    	while(true){
    	EnterCriticalSection(&cs);
    		for(int y(0); y < 5; y++){
    		cout << p->array[y] << endl;
    		}
    	i++;
    	LeaveCriticalSection(&cs);
    	}
    return 0;
    }
    
    // +---------------------------------------------------------------------------
    // +  main - Methode
    // +---------------------------------------------------------------------------
    
    int main(void) 
    {
    
    	// HANDLES und VARIABLEN
    	HANDLE hThread1, hThread2;
    	DWORD dwThreadId1, dwThreadId2;
    	DWORD wait1, wait2;
    	InitializeCriticalSection(&cs);
    
    	hThread1 = CreateThread( 
    		        NULL,              // default security attributes
    			    0,                 // use default stack size  
    		        ThreadProc1,        // thread function
    			    (LPVOID) &daten,             // argument to thread function
    			    0,                 // use default creation flags
    			    &dwThreadId1);   // returns the thread identifier 
    
    	hThread2 = CreateThread(
    				NULL,              // default security attributes
    				0,                 // use default stack size  
    				ThreadProc2,        // thread function 
    				(LPVOID) &daten,    // argument to thread function 
    				0,                 // use default creation flags 
    				&dwThreadId2);   // returns the thread identifier 
    
    	while(true){
    		if (_kbhit()){
    			SetEvent( hEvent );
    			break;
    		}
    
    		Sleep(100);
    	}	
    
    	wait1 = WaitForSingleObject(
    			 hThread1,
    			 INFINITE
    	);
    
    	wait2 = WaitForSingleObject(
    			 hThread2,
    			 INFINITE
    	);
    
    // ENDE
    	DeleteCriticalSection(&cs);
    
    	system("Pause");
         return 0;
    }
    

    Könnte mir jemand zeigen wie ich folgendes realisieren kann:
    Ich möchte, das nach einem Tastendruck (_kbhit()) von der main aus beide Threads geordnet beendet werden. Das ganze soll mittels Events geschehen.



  • if(WaitForSingleObject(hEvent,0)==WAIT_TIMEOUT)
      break;
    

    ^^ das da mußt du an geeigneter Stelle in die Hauptschleife bieder Threads einbauen, um auf deine SetEvent() reagieren zu können. (der beste Platz ist zwischen dem LeaveCriticalSection() und dem Schleifenabschluß)



  • Wenn ich es so mache gibt er mir 00000 aus und bleibt dann stehen obwohl ich keine taste gedrückt habe...

    if(WaitForSingleObject(hEvent,0)==WAIT_TIMEOUT)
      break;
    

    Das abbuch Kriterium soll aber auch nicht ein time out sondern des hEvent sein was gesignald wird.



  • Nachtrag:

    if(WaitForSingleObject(hEvent,INFINITE)==WAIT_OBJECT_0)
    	break;
    

    Damit erziele ich komischerweise das gleiche Ergebnis.



  • // im Hauptprogramm, vor anlegen der Threads:
    hEvent = ::CreateEvent(0, true, 0, 0);
    if (!hEvent)
    {
        std::cout << "Dah, nix mit Event!" << std::endl;
        return 1;
    }
    
    // in der Schleife:
    if (::WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
        break;
    
    // im Hauptprogramm nach dem Warten auf nen Tastendruck:
    ::SetEvent(hEvent);
    


  • Danke jetzt geht es!

    Jetzt hab ich aber noch eine Frage.

    WaitForSingleObject(hEvent, 0)
    

    Was bewirt hier die 0. Und warum geht INFINITE (keine zeit Beschränkung) nicht?



  • Die 0 ist die max. Wartezeit, und INFINITE führt dazu dass "ewig" gewartet wird, d.h. die Funktion kehrt erst zurück wenn das Objekt "signaled" ist.
    Da du an der Stelle nur abfragen willst ob es signaled ist und nicht warten übergibst du eben 0.



  • @Laines:
    Kannst du noch einmal den gesamten Code posten, mit dem Beenden duch Tastendruck?


Anmelden zum Antworten