Multithreading und GetMessage



  • Hallo zusammen,

    vielen Dank für eure Antworten! 👍

    Bzgl. den Antworten von hustbaer und Herr Richter: Stimmt es dann, dass wenn ich ein Programm mit der <thread> Bibliothek von C/C++ unter Linux (beispielsweise in Ubuntu) compiliere/ausführe, auch eine Ubuntu API oder etwas Ähnliches aufgerufen wird?

    Bzgl. meiner Ursprungsfrage, würde sich mein Programmiervorhaben mit der vereinfachten <thread> Bibliothek umsetzen lassen oder woran würde/könnte es scheitern?

    Zu Wade1234s Antwort: Gibt es noch weitere Vorteile der Windows API, außer Prioritäten? Vielleicht hättet ihr noch einen Link speziell zum Thema multithreading für mich. 🙄 Denn offensichtlich ist das ein unglaublich komplexes Thema, nur kann ich die Schwierigkeit noch nicht erkennen. 😞 In reinem C/C++ habe ich mich schon mit diesem tutorial ( https://www.youtube.com/playlist?list=PL5jc9xFGsL8E12so1wlMS0r0hTQoJL74M ) beschäftigt. In diesem Link ( https://www.spieleprogrammierer.de/27-tutorials/6661-einstieg-in-multithreading-unter-windows/ ) konnte ich die Schwierigkeit von multithreading leider auch nicht nachvollziehen...

    @Herr Richter, könnten Sie mir vielleicht noch die "Geschmacksache" näher erläutern? Also, was an der Einbindung von <thread> als negativ angesehen wird.

    Ganz, ganz lieben Dank euch allen, mühsam ernährt sich das Eichhörnchen! 🙂



  • Martin Richter schrieb:

    AnfängerX schrieb:

    Wo ist denn der genaue Unterschied, was ist der Vorteil eines WindowsThreads gegenüber eines threads aus der C-Bibliothek? Wieso hat Windows hier eigene Funktionen? 😕

    C/C++!=OS

    Meinst Du die C Compiler bringen Ihr eigenes OS mit?

    Jetzt blamiere ich mich wahrscheinlich:
    Ich dachte immer, dass das OS aus einer Hochsprache entspringt, wie z.B. C/C++, und das diese der Grundstein für ein OS ist ...



  • Bei ihm kannst du schön was lernen: Mr. Newcomer (Herr Richter kennt ihn sogar persönlich [Ne, ich hab das nicht vergessen, Martin ;)])
    http://www.flounder.com/mvp_tips.htm#hreads and Processes series


  • Mod

    AnfängerX schrieb:

    Ich dachte immer, dass das OS aus einer Hochsprache entspringt, wie z.B. C/C++, und das diese der Grundstein für ein OS ist ...

    Nein! Es ist höchstens die Sprache in der es geschrieben wurde.

    Ansonsten hat ein OS und eine Bibliothek einer Sprache (wie thread) soviel gemeinsam wie eine Autofabrik und ein Werkzeugkasten. (OK etwas übertrieben... :D)

    Die Compiler Hersteller müssen sowas wie die C-Runtime immer auf ein OS anpassen... Dito solche std-Bibliotheken.



  • AnfängerX schrieb:

    Gibt es noch weitere Vorteile der Windows API, außer Prioritäten?

    naja du kannst eben "alles" konfigurieren, das muss aber nicht unbedingt ein vorteil sein.

    Denn offensichtlich ist das ein unglaublich komplexes Thema, nur kann ich die Schwierigkeit noch nicht erkennen.

    die probleme fangen auch erst an, wenn mehrere threads auf eine variable zugreifen. wenn also 1500€ auf dem bankkonto liegen und thread1 900€ abheben will und thread2 1000€, dann zahlt die bank möglicherweise zuviel aus und das muss verhindert werden.



  • Hallo zusammen,

    vielen Dank für eure zahlreiche Hilfe und den neuen Link!

    Ich werde mich noch einmal in Ruhe mit dem Link beschäftigen. Aber wenn - jetzt nur beim drüber lesen - mutex oder CriticalSection nicht ordnungsgemäß funktionieren, dann verstehe ich die Komplexität meines Vorhabens... Allerdings stellt sich dann auch mein Programmierweltbild auf den Kopf. Denn wenn beispielsweise die Bibliothek <mutex> nicht funktioniert, funktionieren denn dann eigentlich alle anderen Bibliotheken richtig? Ich lese doch etwas falsch?! 😮
    Naja und in logischer Konsequenz kann ich dann natürlich auch nicht die einfache <thread> Bibliothek nutzen, sondern benötige die Windows API. Und ich darf mir etwas einfallen lassen, wie ich die Sychronisierung regle und welche Elemente überhaupt vor Mehrfach-Zugriff geschützt werden müssen. Vielleicht könntet ihr mir das noch mit einem kurzen "ja" bestätigen?

    Nochmal ganz lieben Dank! 👍 und ich habe mir da ja ein wunderschönes Projekt herausgesucht 😞


  • Mod

    AnfängerX schrieb:

    Aber wenn - jetzt nur beim drüber lesen - mutex oder CriticalSection nicht ordnungsgemäß funktionieren, dann verstehe ich die Komplexität meines Vorhabens... Allerdings stellt sich dann auch mein Programmierweltbild auf den Kopf. Denn wenn beispielsweise die Bibliothek <mutex> nicht funktioniert, funktionieren denn dann eigentlich alle anderen Bibliotheken richtig? Ich lese doch etwas falsch?! 😮

    Wer sagt, dass Mutex und CriticalSection NICHT gehen?
    Woraus schließt DU das?



  • Wohl aus Avoid CMutex, CEvent, CSemaphore and CCrticalSection, also die MFC-Implementierungen!!!

    Aber davon war ja in diesem Thema nie die Rede, denn die C++ Standard-Bibliotheken <thread> und <mutex> werden wohl korrekt umgesetzt worden sein.



  • von mutex und co rede ich gar nicht. du wirst schon merken, was ich meine, wenn da nachher fehler auftreten und du das ganze debuggen darfst.

    AnfängerX schrieb:

    und ich habe mir da ja ein wunderschönes Projekt herausgesucht 😞

    hast du ja auch. also mir macht sowas spaß!

    so kompliziert sind mutexes in der winapi aber auch nicht, du kannst sie also problemlos verwenden: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686927(v=vs.85).aspx


  • Mod

    Th69 schrieb:

    Wohl aus Avoid CMutex, CEvent, CSemaphore and CCrticalSection, also die MFC-Implementierungen!!!

    Aber davon war ja in diesem Thema nie die Rede, denn die C++ Standard-Bibliotheken <thread> und <mutex> werden wohl korrekt umgesetzt worden sein.

    Ich gehe in vielen Dingen nicht mit Joseph konform. Wie auch hier...
    Joseph ist/war (ich weiß es nicht) sehr speziell. Ich glaube am liebsten würde er es lieben wenn alle noch Assembler programmieren... 😉



  • Martin Richter schrieb:

    Ich gehe in vielen Dingen nicht mit Joseph konform. Wie auch hier...
    Joseph ist/war (ich weiß es nicht) sehr speziell. Ich glaube am liebsten würde er es lieben wenn alle noch Assembler programmieren... 😉

    The Best Synchronization Is No Synchronization: Alternatives to semaphores, mutexes, and CRITICAL_SECTIONs

    http://www.flounder.com/no_synchronization.htm

    It is easier to reason about synchronization when you use protocols like Positive Handoff and Central Controller than if you try to reason about mutexes and semaphores. Because there is no explicit synchronization, there is no possibility of deadlock.

    Da ist schon was dran. Mit einem "Central Controller" bin ich immer sehr gut gefahren.



  • Th69 schrieb:

    Wohl aus Avoid CMutex, CEvent, CSemaphore and CCrticalSection, also die MFC-Implementierungen!!!

    In dem Artikel geht es hauptsächlich darum dass der Autor nicht verstanden hat wie man CSingleLock verwendet, daraus dann falsche Schlüsse zieht und behauptet dass CMutex und CCriticalSection "broken" wären. Das einzige was broken ist ist allerdings sein verständnis von CSingleLock .

    (OK, das ist nicht das einzige worum es in dem Artikel geht. Ein paar der anderen Punkte sind valide, aber für die meisten Anwendungen nicht von besonders grosser Bedeutung.)



  • Hallo zusammen,

    vielen Dank für eure zahlreichen Beiträge. 👍

    Bei mir ist es momentan leider etwas stressig, sodass ich nicht vor nächstem Wochenende dazu kommen werde, etwas zu programmieren. Mit euren zahlreichen Links sollte ich es aber schaffen, ich werde sowohl thread als auch die mutexes aus der Win API nehmen. Das sollte am Sinnvollsten sein.

    Wenn ihr also nicht noch weiter über den Autor des einen Links diskutieren wollt, könnt ihr das Thema schließen, ich steige bei der Diskussion leider aus.

    Ganz lieben Dank noch einmal!

    AnfängerX



  • Ich muss leider sagen, dass ich Mr. Newcomers Urteil weit mehr vertraue als hustbaers.



  • Es ist vollkommen egal wem du mehr vertraust. Das ist keine wischi-waschi Einschätzung wo es Meinungen geben kann. Das ist einfach so.
    CSingleLock ist wie std::unique_lock dafür gedacht dass man es auf den Stack legt. Lokale Variable innerhalb einer Funktion. Bzw. ganz explizit nicht dafür gedacht concurrent verwendet zu werden.

    Wer sich darüber aufregt dass es nicht thread-safe ist und/oder dass man damit nicht rekursiv locken kann, der hat das schlicht und ergreifend nicht verstanden.


  • Mod

    hustbaer schrieb:

    Th69 schrieb:

    Wohl aus Avoid CMutex, CEvent, CSemaphore and CCrticalSection, also die MFC-Implementierungen!!!

    In dem Artikel geht es hauptsächlich darum dass der Autor nicht verstanden hat wie man CSingleLock verwendet, daraus dann falsche Schlüsse zieht und behauptet dass CMutex und CCriticalSection "broken" wären. Das einzige was broken ist ist allerdings sein verständnis von CSingleLock .

    (OK, das ist nicht das einzige worum es in dem Artikel geht. Ein paar der anderen Punkte sind valide, aber für die meisten Anwendungen nicht von besonders grosser Bedeutung.)

    👍

    Genau... 🙂



  • EOP schrieb:

    Mit einem "Central Controller" bin ich immer sehr gut gefahren.

    ich habe mal etwas programmiert, bei dem sich die einzelnen threads bei einem "steuer-thread" in eine warteschleife eingetragen und dann aktiv mit sleep gewartet haben, bis sie an der reihe waren.

    ist das sowas? bing spuckt da irgendwie nur müll aus.



  • Bei mir ging es eigentlich nur um HTTP-threads.
    Die threads senden ihre Aufgabenanforderungen und Datenergebnisse per PostMessage an einen "Central Controller", der das verwaltet, Aufgaben zuteilt und neue Aufgabe versendet.
    Funktioniert auch mit 256 threads hervorragend und echt flott.



  • Hallo zusammen,

    lange ist es her, aber nachdem der Thread noch offen ist und ich am Verzweifeln, würde ich mich erneut sehr über eure Hilfe freuen.

    Grundsätzlich laufen die beiden Threads parallel ab und hypothetisch funktioniert es. In der Praxis jedoch sperrt Thread A, der die Auf- und Abbewegung des Balls steuert, ununterbrochene die Ressource bzw. das Fenster, sodass händische Eingaben nicht möglich sind, So ist es mir nicht möglich, das Programm zu schließen und ich sehe ununterbrochen das Windows-Ladesymbol.
    Implementiere ich in Thread A jedoch vor der Ressourcensperrung eine aufwändige Rechenaufgabe, kann ich das Programm wunderbar schließen oder andere händische Eingaben machen, nur hängt dann auch das Bild. 😞 😞

    #include <Windows.h>
    #include <tchar.h>
    #include <ctime>
    #include "Graphics.h"
    
    Graphics *bitte = NULL;
    CRITICAL_SECTION window;
    bool TAbbruch = false;
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMSG, WPARAM wParam, LPARAM lParam) {
    
    	switch (uMSG)
    	{
    	case WM_CLOSE:
    		if (MessageBox(hwnd, _T("Are you sure?"), _T("noPlan"), MB_OKCANCEL) == IDOK) {
    			DestroyWindow(hwnd);
    			PostQuitMessage(0);
    		}
    		return 0;
    	}
    
    	return DefWindowProc(hwnd, uMSG, wParam, lParam);
    }
    
    DWORD WINAPI ThreadProc() {
    
    	float y = 150;
    	float ySpeed = 0.0;
    
    	time_t previous = time(0);
    	time_t lag = 0.0;
    
    	while (!TAbbruch)
    	{
    		/*time_t current = time(0);
    		time_t elapsed = current - previous;
    		previous = current;
    		lag += elapsed;
    
    			while (lag >= 0.0000000000001) {
    			*/
    
    				ySpeed += 3.0;
    				y += ySpeed;
    
    				if (y > 600) {
    					y = 600;
    					ySpeed = -50;
    				}
    
    				EnterCriticalSection(&window);
    				bitte->cls(1.0, 1.0, 1.0, 1.0);
    				bitte->Ball(375.0f, y, 90);
    				LeaveCriticalSection(&window);
    
    				//lag -= 0.0000000000001;
    			//}
    
    	}
    
    	return 0;
    }
    
    int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pcmdline, int nCmdShow)
    {
    	WNDCLASSEX wndc;
    	ZeroMemory(&wndc, sizeof(WNDCLASSEX));
    	wndc.cbSize = sizeof(WNDCLASSEX);
    	wndc.style = CS_HREDRAW | CS_VREDRAW;
    	wndc.lpfnWndProc = WindowProc;
    	wndc.hInstance = hInstance;
    	wndc.hbrBackground = (HBRUSH) COLOR_WINDOW;
    	wndc.lpszClassName = _T("MainWindow");
    
    	RegisterClassEx(&wndc);
    
    	RECT rect = { 0, 0, 800, 600 };
    	AdjustWindowRectEx(&rect, WS_OVERLAPPEDWINDOW, false, WS_EX_OVERLAPPEDWINDOW);
    
    	HWND hwnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, wndc.lpszClassName, _T("DirectX"), WS_OVERLAPPEDWINDOW, 100, 100, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hInstance, NULL);
    
    	if (!hwnd) {
    
    		DWORD err = GetLastError();
    		TCHAR output[100];
    		_stprintf_s(output, _T("%s") , err);
    
    		MessageBox(NULL, (LPCWSTR) output, NULL, MB_OK);
    
    		return -1;
    	}
    
    	bitte = new Graphics();
    	if (!bitte->Init(hwnd)) {
    		delete bitte;
    		return -1;
    	}
    
    	ShowWindow(hwnd, nCmdShow);
    
    	InitializeCriticalSection(&window);
    
    	HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadProc, NULL, 0, NULL);
    
    	MSG msg = {};
    
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    
    		TranslateMessage(&msg);
    
    		EnterCriticalSection(&window);
    		DispatchMessage(&msg);
    		LeaveCriticalSection(&window);
    	}
    	TAbbruch = true;
    	Sleep(5000);
    
    	CloseHandle(thread);
    	DeleteCriticalSection(&window);
    	delete bitte;
    
    	return 0;
    }
    

    Ich bin um jeden Rat dankbar!



  • Ist doch klar: dein Thread ballert so schnell wie möglich durch die Schleife und hält dabei fast ununterbrochen die CriticalSection. Folglich bleibt fast keine Zeit mehr für die Nachrichtenschleife des Mainthreads; diese wird fast nur am Warten sein.

    PS: Du hast mindestens ein Data Race zwischen deinem Thread und dem Mainthread. Der Thread läuft auch noch, wenn das Fenster schon geschlossen wurde, folglich ist das HWND im Thread ungültig. TAbbruch muss außerdem atomic sein.


Anmelden zum Antworten