Problem mit messages, critical section und Sleep...
-
Hey!
Erst einmal der Code, ein Minimalbeispiel, welches mein Problem zeigt:
HWND dialogHandle; HWND button; long running = true; CRITICAL_SECTION cs; void ChangeStatus(int status) { EnterCriticalSection(&cs); switch(status) { case 1: { //SendMessage(dialogHandle, WM_SETTEXT, 0, reinterpret_cast<LPARAM>("Closing")); // Deadlock //SendNotifyMessage(dialogHandle, WM_SETTEXT, 0, reinterpret_cast<LPARAM>("Closing")); // Text wird nicht gesetzt break; } } LeaveCriticalSection(&cs); } void OnButtonClicked() { InterlockedExchange(&running, false); Sleep(1000); ChangeStatus(1); } unsigned int __stdcall Thread(void* param) { while(InterlockedExchange(&running, running)) ; ChangeStatus(1); return 0; } __w64 int __stdcall DialogProcess(HWND dialogHandle, unsigned message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_COMMAND: { switch(LOWORD(wParam)) { case IDCANCEL: { DestroyWindow(dialogHandle); return true; } } switch(HIWORD(wParam)) { case BN_CLICKED: { OnButtonClicked(); return true; } } break; } case WM_CLOSE: { DestroyWindow(dialogHandle); return true; } case WM_DESTROY: { PostQuitMessage(0); return true; } } return false; } int __stdcall WinMain(HINSTANCE instanceHandle, HINSTANCE, char*, int) { InitCommonControls(); InitializeCriticalSection(&cs); dialogHandle = CreateDialog(instanceHandle, MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProcess); button = GetDlgItem(dialogHandle, IDC_BUTTON1); _beginthreadex(0, 0, Thread, 0, 0, 0); MSG message; while(GetMessage(&message, 0 , 0, 0)) { TranslateMessage(&message); DispatchMessage(&message); } }Nun, wird der Button geklickt, gerät der Nebenthread aus der Schleife und ruft sogleich ChangeStatus() auf. Dort bekommt er die critical section und soll eine Nachricht an das Hauptfenster (im Hauptthread) schicken.
PostMessage blockiert aber, weil der Hauptthread im Sleep() steckt. Und wenn er aus dem Sleep() heraus ist, ruft er auch ChangeStatus() auf und hängt somit bei EnterCriticalSection() (Im realen Code ruft ChangeStatus() mehrfach SendMessage() auf).Dann habe ich es mit SendNotifyMessage() versucht, aber es hat keinen Effekt.
Was soll ich nun tun?Danke schonmal!
MfG
-
könntes vieleicht gehen, wenn du sleep ersetzt?
z.B. durch nen Timer..?
-
Soweit ich das verfolgen kann, nein. Sleep() erhört die Chance des deadlocks nur auf ~100%.
Ohne Sleep:
- ChangeStatus() aus Thread() wird gerufen, bekommt critical section, ist vor SendMessage()
- ChangeStatus() aus OnButtonClicked() wird aufgerufen, blockiert, weil critical section von Thread() geowned wird
- ChangeStatus() aus Thread() will SendMessage() ausführen, blockiert, weil ChangeStatus() aus OnButtonClicked() auf critical section wartet
-> Deadlock
-
Was willst du hier eigentlich tun?
Der Code - so wie du ihn gepostet hast - ist ja wohl ganz einfach zu fixen: macht den Thread weg - du tust ja offensichtlich nichts darin.
-
Amboss der Rabiator schrieb:
Erst einmal der Code, ein Minimalbeispiel, welches mein Problem zeigt

Und warum funktioniert SendNotifyMessage() nicht?
-
Wieso glaubst Du, dass SendNotifyMessage nicht funktioniert?
Weil Du keine visualle Veränderung siehst?Dasist doch klar. Niemand zeichnet in diesem Fall das Fenster neu, denn der Thread, ist ja blockiert und Du führst keine Fensternachrichten mehr aus.
WM_PAINT wird also auch nicht ausgeliefert.Die Folge: SendNotifyMessage wird ausgelifert und steckt in der Queue fest und wird nicht abgeabeitet...
Zudem besteht das Risiko, dass der Zeiger den WM_SETTEXT verwenden will ungültig wird, solltest Du später auf die Idee kommen Variablen zu nutzen.
-
Aber nach einer Sekunde Sleep werden doch wieder Nachrichten abgearbeitet. Und wenn ich den Dialog nachher über den Bildschirmrand hinaus- und wieder hineinziehe, hat sich der Titel trotzdem nicht verändert. InvalidateRect() hilft auch nicht.