Thread und Dialoge
-
Hi,
ich versuche eine große Dateioperation so zu gestalten, dass der Benutzer einen Wait Dialog angezeigt bekommt, den er auch abbrechen kann.
Leider bekomme ich eine Assertion beim Abbruch und ich weiß nicht wieso.
Hier mein Code
//--CLASS----------------------------------- class: bool m_thrActive; CWait m_Wait; bool m_Flag; void thrRun(); static UINT thrFunction(LPVOID pParam); //--Main Thread------------------------------ void MyApp::OnBtn1() { m_Flag = true; m_thrActive = false; CWinThread* pThread = AfxBeginThread(thrFunction, this); while(!m_thrActive) Sleep(10); if(IDOK==m_Wait.DoModal()) { addLog("Dump complete"); } else { m_Flag=false; addLog("dump failed"); } } //--Translator------------------------------- UINT MyApp::thrFunction(LPVOID pParam) { MyApp* pDlg = (MyApp*) pParam; pDlg->thrRun(); return 0; } //--Work Thread------------------------------ void MyApp::thrRun() { FILE *fp; m_thrActive=true; fp = fopen("test.txt","w"); if(fp==NULL) { MessageBox("error creating file","error",MB_OK); return; } while(m_Flag) { fprintf(fp,"mach irgendwas"); } fclose(fp); if(m_Flag) m_Wait.EndDialog(IDOK); }Danke!
Mod-Edit: In Farbe dürfte der code gleich viel übersichtlicher aussehen

-
Mit einem Dialogfenster darf nur derjenige arbeiten, der es auch angelegt hat. Da ist es klar, daß es kracht, wenn jemand von außen (in deinem Fall der Worker-Thread) versucht, den Dialog abzuschießen.
(mal davon abgesehen, daß du erst zu dem EndDialog()-Aufruf kommst, nachdem der Dialog sich bereits von selbst beendet hat (durch Betätigung der "Abbrechen"-Taste).Du kannst von außen bestenfalls eine Nachricht per SendMessage() oder PostMessage() an diesen Dialog schicken, die er dann verarbeiten müsste.
-
Verwende PostMessage um im worker Thread mit dem Dialog zu kommunizieren.
z.B. PostMessage(WM_USER+123, 0, 0) und im entsprechenden Handler rufst du dann EndDialog auf.
-
Das Problem hier ist dass Du die MFC verwendest. Die MFC benutzt threadafine Message-Maps. In einer puren Win32 API Anwendung wäre es durchaus legitim EndDialog aus einem anderen Thread aufzurufen. Interessanterweise löst EndDialog auch keine Nachricht aus, sondern setzt nur ein Flag in dem Speicher des Fensters, dass die MessageLoop terminiert.
Die Tipps von CStoll und hustbaer sind der richtigte Weg. PostMessage verwenden und eine entsprechende Nachricht versenden. Wenn es Dir um das direkte Beenden geht würde WM_COMMAND mit IDOK oder IDCANCEL schon den Job machen!
-
vielen Dank!