RichEdit nach der Benutzung wieder freigeben?



  • Freak33 schrieb:

    Also die Console Klassen werden im Main-Thread erstellt. Somit ist die Haut-Queue dafür verantwortlich - das klappt auch alles wunderbar und perfekt bis zum Shutdown.

    Dann ist auch der Haupt-Thread für die Ausgaben verantwortlich (alles andere bereitet Probleme). Aber um ein Sprichwort abzuwandeln - "Ein Code sagt mehr als tausend Worte" 😉


  • Mod

    Freak33 schrieb:

    "Es ist sicherlich kein Problem im Debugger Break All anzuklicken und zu sehen was di"

    Öhm wir mach ich das?

    Debugger laufen lassen. Bis Problem aufttaucht. Dann gibt es in der Button-Leiste den Schalter Break-All. Anklicken. Debug-Thread Window öffnen und die Threads ansehen, was sie tun.



  • Ok, hab ich jetzt gemacht. Hier die laufenden Threads:

    >	2948	__tmainCRTStartup	__tmainCRTStartup	Normal	1
     	436	Win32 Thread	        7c91eb94	        Highest	1
     	2900	Win32 Thread	        7c91eb94	        Normal	0
     	3212	CTable::Run	        7c91eb94	        Normal	1
     	4088	CTable::Run	        7c91eb94	        Normal	1
     	3084	CTable::Run	        7c91eb94 	        Normal	1
     	380				                        0
    

    Und an folgender Stelle bleibt er hängen:

    void CTableManager::Release()
    {
    	for( int table=0; table < m_aTables.size(); table++ )
    	{
    >		m_aTables.at(table)->Stop();  // HIER
    	}
    }
    

    Die Methode "Stop" schaue folgendermaßen aus:

    BOOL CTable::Stop()
    {
    	if( m_bInit )
    	{
    		m_bStop = TRUE;
    		WaitForSingleObject( m_hRunThread, 10000 );
    		CloseHandle( m_hRunThread );
    
    		return TRUE;
    	}
    	return FALSE;
    }
    

    So, WaitForSingleObject() scheint wohl die Ursache zu sein. Wenn ich die Funktion entferne, werden alle Threads durch den Primär Thread zum Ende gezwungen.

    Hier mal ein Ausschitt aus der CTable::Run

    DWORD WINAPI CTable::Run( LPVOID lpParam )
    {
    
    	// pointer
    	CTable *pT = (CTable*)lpParam;
    
    	// do some updates
    	while( !pT->m_bStop )
    	{
                    // Wenn diese Zeile weg ist, klappt alles wunderbar
    		pT->m_cConsole.AddLine( "Update" );
    
    		Sleep(0);
    	}
    
    	OutputDebugString( "\n Thread Finished" );
    
    	return 2;
    }
    


  • Achja, die Funktion AddLine schaut folgendermaßen aus:

    void CConsole::AddLine( char *msg )
    {
    	if( m_hWnd != NULL )
    	{
    		int length = (int)SendMessage( m_hWndConsole, WM_GETTEXTLENGTH, 0, 0 );
    		SendMessage( m_hWndConsole, EM_SETSEL, length, length );
    		SendMessage( m_hWndConsole, EM_REPLACESEL, TRUE, (LPARAM)msg );
    	}
    
    }
    


  • Ok, es gibt auf jedenfall eine Verbindung zwischen den RichEdit funktionen (egal was passiert Ob man texte einfügt ob nur die Länge des Textes abgefragt wird), wenn ich das in einem Thread aufrufe und parallel WaitForSingleObject aufrufe gibt es Probleme.

    Wobei ich nicht glaube, dass das Problem bei WaitSingleObject liegt - Hier wird nur gewartet bis der Thread beendet wird (Was er nicht tut).

    Es muss ein Problem sein, was mit Thread und einer RichEdit Komponente zu tun hat.

    Jemand eine Idee?? 🙄



  • Neue Theorie:

    Könnte es sein, dass durch WaitForSingleObject() Die RichEditKomponente keine Nachrichten mehr verarbeiten kann (da dadurch der Primär-Thread mit der Msg-Queue lahmgelegt ist)?


  • Mod

    Genau das passiert! Du wartest auf den Thread und nun können keine Nachrichten mehr empfangen werden. Verwende MsgWaitForMutipleObjects und lass die Message Loop weiter laufen.
    Es ist gar nicht gut, dass das RTF Control in einem anderen Thread liegt!
    Warum machst Du das überhaupt?



  • Also ich hab das mal mit "MsgWaitForMultipleObjects" ausprobiert - war aber kein Erfolg.

    MsgWaitForMultipleObjects( 1, &m_hRunThread, TRUE, INFINITE, QS_ALLINPUT );
    CloseHandle( m_hRunThread );
    

    Mit folgendem Code klappt alles wunderbar:

    while( m_bThreadRunning )
    {
    	CBaseApp::GetApp()->ProcessMessageQueue();
    	Sleep(0);
    }
    

    Mit CBaseApp::ProcessMessageQueue

    void CBaseApp::ProcessMessageQueue()
    {
    	MSG msg;
    	if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
    	{
    		TranslateMessage(&msg); 
    		DispatchMessage(&msg); 
    	}
    }
    

    Warum machst Du das überhaupt?

    Das ist automatisch so, da die Klasse CConsole im Primär-Thread erstellt wird und damit auch zu dieser Queue "gehört"!!
    Wie könnte man das denn anders regeln? -> Somit hätte jeder Thread eine eig. Queue?


  • Mod

    1. MsgWaitForMultipleObjects returniert auch, wenn eine Nachriht in der Message Queue drin ist! Dann muss also auch die Nachrichtenschleife laufen. Diese Funktion behandelt keine Nachrichten!

    2. Ich verstehe immer noch nicht was CConsole ist! Das ist das RTF Control?

    Wenn Du also Nachrichten aus den anderen Threads bekommst, dann musst Du auch bis zum letzten Moment auf Nachrichten reagieren.
    Also
    MsgWaitForMultipleObjects durchführen.
    Wenn eine Nachricht vorhanden ist, diese bearbeiten.
    Solange das weiter machen, bis alle Threads terminiert haben.


  • Mod

    BTW:
    Dein Code:

    int length = (int)SendMessage( m_hWndConsole, WM_GETTEXTLENGTH, 0, 0 ); 
         SendMessage( m_hWndConsole, EM_SETSEL, length, length ); 
         SendMessage( m_hWndConsole, EM_REPLACESEL, TRUE, (LPARAM)msg );
    

    Ist nicht threadsicher. Was passiert wenn zwei Threads gleichzeitig hier die Nachrichten "durcheinander" senden. Also nachdem du WM_GETETXTLENGTH ausgeführt hast ein anderer Thread die Länge verändert.

    Du solltest Dir einen anderen Mechanismus für die Nachrichten ausdenken.


Anmelden zum Antworten