Threads



  • ok, danke
    nun waere es aber ersteinmal interessant wieso meine applikation nach dem beenden noch weiter laeuft, siehe eine seite zuvor ganz unten

    ich vermute das der winthread in suspend reingeht statt zu beenden, nur AfxEndThread, WM_QUIT, SendExitCode und was es nicht alles gibt an den verschiedenen positionen bringt alles nichts
    das ist der aufbau

    (CMain ist die CWinThread klasse)
    einstieg in der CTestApp::InitInstance -> CMain::InitInstance -> CMainFrame


  • Mod

    Mr Evil schrieb:

    CWinThread *thread = AfxBeginThread(RUNTIME_CLASS(CMain));
    thread->Run();

    Falsch falsch falsch.

    Dadurch startest Du einen Thread, aber fürhrst eine MessagePump im alten Thread aus. Der neue hat dann keine.


  • Mod

    Wenn Dein neuer Thread im Run ist. Muss er irgendwer AfxPostQuitMessage ausführen.
    Wenn Dein neuer Thread ein m_pMainWnd in sein CWinThread Objekt setzt, terminiert Run automatisch, wenn dieses Fenster zerstört wird.



  • Martin Richter schrieb:

    Mr Evil schrieb:

    CWinThread *thread = AfxBeginThread(RUNTIME_CLASS(CMain));
    thread->Run();

    Falsch falsch falsch.

    Dadurch startest Du einen Thread, aber fürhrst eine MessagePump im alten Thread aus. Der neue hat dann keine.

    Hmm - und wie funktionierts dann richtig, bin nu voellig ratlos, kannst ja die TestApp anschaun, wenn ich das Thread->Run() weg lass, startet gar nichts


  • Mod

    Hats Du gelesen was ich geschrieben habe? Nein...

    Also nochmal
    InitInstance überschreiben in Deiner neue Klasse überschreiben. Und dort Dein Fenster erzeugen und am Ende Run/DoModal ausführen und FALSE returnieren.

    Aonsonsten InitInstance ausführen. Das eigene Fenster erzeugen und TRUE returnieren. Run wird dann ausgeführt.

    Das ist doch nicht anders als in einem normalen MFC Programm.

    Dein Thread terminiert durch zerstören des Main-Fensters...



  • doch hab ich, nur ich bekomm nichts hin (Siehe seite 1 am ende die TestApp zum DL)
    mein einstiegspunkt der applikation ist die CTestApp : CWnd

    CTestApp : CWnd

    BOOL CTestAppApp::InitInstance()
    {
    	CWinThread *thread = AfxBeginThread(RUNTIME_CLASS(CMain));
    	thread->Run();
    // wenn ich hier thread->Run() weg lass, startet ueberhaupt nichts
    	return TRUE;
    }
    

    CMain : CWinThread

    BOOL CMain::InitInstance()
    {
        CMainFrame* pFrame = new CMainFrame;
        if (!pFrame)
            return FALSE;
        m_pMainWnd = pFrame;
        pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE, NULL, NULL);
        pFrame->ShowWindow(SW_SHOW);
        pFrame->UpdateWindow();
        //this->Run(); // bewirkt nichts
        return TRUE;
    }
    

    in MainFrame ist dann die normale erstellung der fenster


  • Mod

    Lass bitte das RUN aus dem Mainthread weg...
    Und was ist nun Dein Problem?



  • Wenn ich in der TestApp::InitInstance das Run weg lasse, startet nichts
    und in dem CMain habe ich gar kein Run aktiv

    Bei diesem versuch startet die applikation nicht

    BOOL CTestAppApp::InitInstance()
    {
    	CWinThread *thread = AfxBeginThread(RUNTIME_CLASS(CMain));
    	//thread->Run();
    	return FALSE;
    }
    BOOL CMain::InitInstance()
    {
    	CMainFrame* pFrame = new CMainFrame;
    	if (!pFrame)
    		return FALSE;
    	m_pMainWnd = pFrame;
    	pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE, NULL, NULL);
    	pFrame->ShowWindow(SW_SHOW);
    	pFrame->UpdateWindow();
    	return FALSE;
    }
    

    bei diesem test startet das programm auch nicht

    BOOL CTestAppApp::InitInstance()
    {
    	CWinThread *thread = AfxBeginThread(RUNTIME_CLASS(CMain));
    	//thread->Run();
    	return FALSE;
    }
    BOOL CMain::InitInstance()
    {
    	CMainFrame* pFrame = new CMainFrame;
    	if (!pFrame)
    		return FALSE;
    	m_pMainWnd = pFrame;
    	pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE, NULL, NULL);
    	pFrame->ShowWindow(SW_SHOW);
    	pFrame->UpdateWindow();
    	this->Run();
    	return FALSE;
    }
    

    bei dieser ist das alt bekannte problem dass die applikation sich nicht beendet und wie du meintest nicht in dem thread laeuft

    BOOL CTestAppApp::InitInstance()
    {
    	CWinThread *thread = AfxBeginThread(RUNTIME_CLASS(CMain));
    	thread->Run();
    	return FALSE;
    }
    BOOL CMain::InitInstance()
    {
    	CMainFrame* pFrame = new CMainFrame;
    	if (!pFrame)
    		return FALSE;
    	m_pMainWnd = pFrame;
    	pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE, NULL, NULL);
    	pFrame->ShowWindow(SW_SHOW);
    	pFrame->UpdateWindow();
    	return FALSE;
    }
    

  • Mod

    Argh....
    InitInstance muss TRUE returnieren sonst wir dintern Run nicht ausgeführt.

    Was hälst Du davon, wenn Du einfach mal Debuggst, was die MFC eigentlich macht.
    Habe ich das nicht (auch) geschrieben!

    Nur wenn Du DoModal verwendets oder selbr Run aufruft, darfst Du FALSE returnieren.
    Es ist kein Stück anders als bei einer normalen Applikation! ⚠



  • auch mit return TRUE; startet die applikation nicht

    startet nicht:

    BOOL CTestAppApp::InitInstance()
    {
        CWinThread *thread = AfxBeginThread(RUNTIME_CLASS(CMain));
        //thread->Run();
        return TRUE;
    }
    BOOL CMain::InitInstance()
    {
        CMainFrame* pFrame = new CMainFrame;
        if (!pFrame)
            return FALSE;
        m_pMainWnd = pFrame;
        pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW|FWS_ADDTOTITLE, NULL, NULL);
        pFrame->ShowWindow(SW_SHOW);
        pFrame->UpdateWindow();
        //this->Run()
        return TRUE;
    }
    

    hab auch die anderen moeglichkeiten wie mein letztes post zeigt probiert mit return TRUE, welches das selbe verhalten aufweist


  • Mod

    Was macht der Hauptthread?

    Schick mir doch mal einen Link für Dein Projekt, dann kann ich mir das mal heute Abend in Ruche ansehen.



  • Vielen vielen dank fuer deine geduld

    schau mal hier:
    Klick
    CTestApp:CWnd -> CMain:CWinThread -> CMainFrame:CFrameWnd -> CLeft:CFormView|CRight:CFormView



  • Beim Debugging wird folgende Meldung ausgegeben:

    Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.

    Man muss also auch m_pMainWnd von CTestAppApp auf irgendetwas zeigen lassen. Im Thread könnte das allerdings schon zu spät sein.



  • wenn ich "m_pMainWnd" auf "thread" verweise, wird die app zwar gestartet, aber nun wieder das problem dass das programm sich nicht richtig beendet, dh der prozess bleibt aktiv


  • Mod

    Der Hauptthread muss natürlich in irgend einer Weise warten...

    Bitte beachtet das m_pMainWin in jedem CWinThread Objekt existiert, also im CWinApp und im CWinThread!



  • da schwebt n riesen fragezeichen ueber mein kopf


  • Mod

    Mr Evil schrieb:

    da schwebt n riesen fragezeichen ueber mein kopf

    Bzgl. was?

    Also Dein erzeugter CWinThread hat ein m_pMainWnd und Dein CWinApp ist von CWinThread abgeleitet und hat auch ein m_pMainWnd Member.

    Alle CWinThread (ob CWinApp oder anderes) verhalten sich immer gleich.
    - Bei Start wird InitInistance geladen. Returniert die Funktion FALSE wird Thread/Applikation beendet.
    - Wird TRUE returniert wird Run aufgreufen wenn ein m_pMainWnd vorhanden ist.
    - Der Thread terminiert wenn das m_pMainWnd zerstört wird.

    Egal ob CWinApp oder GUI Thread.

    Wenn Dein Main Thread jetzt einen neuen GUI Thread startet, dann muss der Mainthread ja nun was tun wenn er InitInstance verlässt. Entweder er wartet auf den anderen Thread, oder er erzeugt selber ein Fenster und geht in den Run, nachdem InitInstance beendet wurde.

    So schwer? 🕶



  • also theoretisch glaub ich das zu verstehen, aber ich weiss nicht wie ich das in meiner app umsetzen muss
    ich hab derzeit das m_pMainWnd auf den thread verwiesen direkt nach den AfxBeginThread in der CTestApp
    nun laeuft die applikation, aber ich weiss nichts, laeuft sie auch in nem thread, ich glaube nicht, denn nach beenden laeuft die exe weiter sodass ich sie im taskmanager killen muss

    // generell ist das mein problem, ich les "starte danach das" - dann stell ich mir die frage, WO und WIE
    ich weiss die ganze zeit so gut wie nie wo genau ich was machen muss, in den Init von der einstiegsklasse, oder dich in der WinThread klasse, oder gar noch spaeter, wenn ja, was muss ich vorher machen usw
    darum hatte ich ja die TestApp geadded


  • Mod

    Dann frage ich mal grundsätzlich: Für was willst Du denn den GUI-Thread verwenden, wenn Dein Mainthread keine GUI hat.

    Ich verstehe Deine Absicht nicht.
    2 GUI-Threads können Sinn machen, müssen aber nicht.



  • was verstehst du unter mainthread ?
    die CMain:CWinThread klasse erstellt doch die MainFrame klasse und dieses zeigt zwei formviews in einen splitter

    schau dir doch ma die TestApp an die ich hier zum DL reingestellt habe - koenntest du die anpassen das das mainframe und die dazugehoerigen formview klassen in einem thread laufen?
    mir fehlt mitlerweile jeglicher ansatz, und hab auch keine idee mehr was ich noch probieren koennte,
    je mehr ich hier les desto weniger weiss ich was ich wo machen muss damit das mainframe in einem thread laeuft #sftz

    ich habe eine
    CTestApp:CWnd welche ein CMainFrame:CFrameWnd klasse aufruft, diese wiederrum besitzt einen splitter mit zwei CFormView fenstern
    diese oberflaeche brauch ich in einem thread
    mein versuch eine CMain:CWinThread dazwischen zu schalten brachte bisher keine erfolge, zu sehen an der TestApp2
    ich raff den scheiss einfach nich, also wie ich dieses doofe mainframe in einem thread bekomm


Anmelden zum Antworten