Threads


  • Mod

    CWinThread *pThread = AfxBeginThread(thread_entry, this); 
            ::WaitForSingleObject(pThread, 10000);
    

    Das dieser Code tödlich ist, ist Dir auch klar.

    Ohne weitere Vorkehrung ist das Threadobjekt nämlich zerstört, wenn der Thread beendet wird und WaitForSingleObject retruniert evtl. nie. (Siehe m_bAutoDelete)



  • Martin Richter schrieb:

    Um einen neuen GUI Thread zu starten erzeugst Du einen eigene Klasse, die Du von CWinThread ableitest. Der verpasst Du DEFINE_/IMPLEMENT_DYNCREATE.

    Dann verwendest Du die Funktion von AfxBeginThread, die den Klassen Namen übernimmt.

    Nun einfach InitInstance überschreiben, Deine Fenster erzeugen und als letztes einfach CWinThread::Run ausführen.

    Thats it...

    Klingt einfach, so hatte ich das auch in erinnerung - mein problem ist die umsetzung

    also
    - VS 05 anwerfen
    - neues MFC projekt mit dem namen TestApp
    - SDI
    - fertig

    nun geh ich zu dem einstiegspunkt in der TestApp.cpp und aendere das CWnd nach CWinThread ab und die dazugehoerigen DYNCREATE usw
    InitInstance ist ja schon da, also schmeiss ich da nur ien paar sachen raus, und lassn compiler laufen
    der bemaengelt nichts
    start -> peng, direkt am start, kommt bei InitInstance nichteinmal rein /=


  • Mod

    Wo änderst Du bitte ein CWnd in ein CWinThread?

    Gib mit mal einen Link auf Dein Demo-Projekt...



  • ich glaube ich hab etwas

    in der InitInstance der TestApp

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

    //CMain ist von CWinThread abgeleitet

    in der InitInstance von CWinThread wirt das MainFrame erstellt und angezeigt
    also das TestApp nicht durch den CWinThread ersetzt sondern diese klasse dazwischen geschaltet !!
    compiler rennt und programm laeuft

    werds morgen ma test umsetzen in meiner anderen app
    wuenscht mir glueck #gg



  • ne frage dazu

    was muss ich beachten um die app nun richtig zu beenden?
    In der MainFrame habe ich OnClose ueberladen fuer postwork, was muss ich nun beachten?

    beim test nun hat es sich ergeben dass - wenn ich das programm schliesse, bleibts im hintergrund noch aktiv



  • Hier ist mal die TestApp
    startet normal und ich glaube auch in nem thread, aber wenn ich es beende, bleibt der task noch aktiv .. zu huelf /=
    Klick for download



  • Bei COM bitte auch beachten dass du CoInitialize(Ex) aufrufen musst. Und dass es 2 verschiedene Apartment-Models gibt, nämlich Multithreaded und Singlethreaded. Und dass man Interface-Zeiger aus einem Apartment nicht in einem anderen verwenden kann, sondern diese Marshalen muss.
    Alles sehr unübersichtlich und etwas kompliziert, vor allem wenn es alles neu für einen ist. Leider.

    Viel mehr als "lies dir einiges zum Thema COM und Apartments durch" kann ich aber auch nicht schreiben, auch nur das wichtigste zusammenzufassen würde über einige Seiten gehen (zumindest wenn man es so formulieren will dass es jmd. verstehen kann der es nicht sowieso schon weiss).



  • 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.


Anmelden zum Antworten