nicht-modaler Dialog & Serielle Kommunikation



  • Hallo,

    in meinem programm sollen von einem Messgerät ca. alle 2 Sekunden Messwerte über die Serielle Schnittstelle ausgelesen werden, und in einem nichtmodalen Dialog dargestellt werden.
    Solange keine Kommunikation aktiv ist, kann ich meinen nichtmodalen Dialog beliebig verschieben, schließen und auch die Uhr in meinem programm läuft.
    Wenn ich nun jedoch über den Serial Port mit dem Messgerät kommuniziere, lässt sich mein Dialog nicht mehr verschieben, nicht mehr schließen und die Uhr hat auch angehalten.
    Kann mir dabei jemand weiterhelfen??



  • wie immer:
    Dein Dialog bekkomt keine Leistung, da Du ja in einer schleife deiner Serellen Schnittstelle hängst. Da ich dein konstrukt nicht kenne, würde ich sagen, Du verschiebst die Kommunikation in einen eigenen Thread, und Überträgst dann die empfangenen Daten an den Dialog. wurde hier schon häufiger diskutiert und in den FAQ ist dazu auch was zu finden.
    2. Möglichkeit du gibst während des empfages zeit frei, also durchläufst die Messageroutiene.

    MSG msg;
    
    while( ::PeekMessage( &msg, NULL, NULL, NULL, PM_NOREMOVE ) )
      ::AfxGetThread()->PumpMessage();
    

    Gruß Matthias



  • Ahja danke CTecS!
    Habe eine Möglichkeit gefunden, es ohne eigenen Thread zu realisieren.
    Wenn das allerdings nicht so gut läuft, werde ich mich wohl mit Threads befassen müssen, hab damit noch nie was zu tun gehabt.
    Wenn jemand ein gutes Tutorial über Threads kennt, sagt mir bitte wo ich das finde.



  • void CMainFrame::OnViewDisplay()
    {
    	BOOL bCancel=FALSE;
    	CDisplay* MyDisplay;  
    	MSG Msg;
    
    	MyDisplay=CDisplay::Instance (&bCancel, this );
    	MyDisplay->InitialDialog ("Messwertfenster");
    
    	MyDisplay->UpdateData(FALSE);
    
        while (bCancel==FALSE)
    	{
         while (::PeekMessage(&Msg, NULL,0,0,PM_REMOVE))
    	   {if (!AfxGetApp()->PumpMessage()) {::PostQuitMessage (0); break;}}
    
    	   if(Msg.message == WM_QUIT) 
            { 
                bCancel==TRUE; 
            } 
            else 
            { 
                TranslateMessage(&Msg); 
                DispatchMessage(&Msg); 
            }
    
    	// hier werden die Befehle 0x10 und 0x0C herausgegeben 
    	// + Variablen des Fensters geändert 
    	      MyDisplay->DisplayCom();
    
        MyDisplay->UpdateData(FALSE);
    	}
    
    	MyDisplay->Done();
    }
    

    Warum funktioniert hier die Nachrichtenbehandlung nicht?



  • Du mußt den Block if(Msg.message==WM_QUIT)... natürlich auch in die Nachrichtenschleife packen und nicht dahinter - sonst bekommst du nur die Nachricht mit, mit der die Nachrichtenschleife beendet wurde.

    PS: Auch wenn es verlockend sein mag, die Nachrichtenverwaltung sleber zu regeln - MFC hat bereits eine eigene NAchrichtenschleife aufgebaut, in die du dich besser nicht einmischen solltest. Da sieht die Lösung mit Threads idR eleganter aus.



  • Ich habe mit Threads noch nie was gemacht, wo kann ich ne gute Starthilfe bekommen?



  • Irgendwie funktionierts auch nicht wenn ich es in die Nachrichtenschleife packe.
    Könntest mal etwas Code posten, wie das aussehen soll?



  • Schau dich mal etwas hier im Board um, da gibt es schon etliche Beiträge zum Thema Threads. Eine weitere Informationsquelle könnte der Abschnitt Multithreading in der MSDN sein.



  • Ok danke, werde das später mal probieren mit Threads.
    Aber zuerst werde ich es noch ohne Thread probieren, aber irgendwie klappt es nicht.
    Wie muss mein Code denn aussehen?



  • maRKus23 schrieb:

    Wie muss mein Code denn aussehen?

    Mit einem Wort: Katastrophal 😃

    Etwas ausführlicher:
    Wie ich oben schon sagte, muß die Weiterverarbeitung der Nachrichten in der Schleife passieren (und in der MSDN gibt es auch einige Erklärungen zur Nachrichtenschleife, nur falls du mehr darüber wissen willst):

    while (bCancel==FALSE)
    {
      while (::PeekMessage(&Msg, NULL,0,0,PM_REMOVE))//Beginn der internen Nachrichtenschleife
      {
        if (!AfxGetApp()->PumpMessage()) {::PostQuitMessage (0); break;}
    
        if(Msg.message == WM_QUIT) 
        { 
          bCancel==TRUE; 
        } 
        else 
        { 
          TranslateMessage(&Msg); 
          DispatchMessage(&Msg); 
        }
      }//Ende der internen Nachrichtenschleife
    
      MyDisplay->DisplayCom();
    
      MyDisplay->UpdateData(FALSE);
    }
    


  • So hab ichs eben gehabt und es hat nicht funktioniert, vllt funktionierts ja jetzt?!



  • nee, es funktioniert nicht.
    Der Dialog lässt sich immer noch nicht verschieben und nicht mehr schließen.



  • es funktioniert, allerdings ist die Performance sehr schlecht, da ich zwischen dem Senden und dem Empfangen mindestens ein Sleep(3000) brauche, da sonst die Daten nicht richtig ausgewertet werden.
    Da dieses Sleep(3000) mein Programm für 3 Sekunden lahmlegt kann ich in der Zeit kein Window verschieben. Ausserdem läuft die Uhr im 3 Sekunden-Takt.
    Hat jemand eine Idee was ich anstelle von Sleep(3000) einsetzen kann?



  • Meine Antwort bleibt immer noch die selbe - lagere die Berechnung in einen extra-Thread aus, der das Hauptprogramm dann über neu ankommende Daten informiert.

    (was genau spricht eigentlich gegen Threads außer einem "ich will nicht"?)



  • Ich werde es dann wohl mit Threads machen müssen.
    Habe halt keine Ahnung wie das mit Threads funktioniert, aber in einem halben Jahr müsste ich mich wohl eh damit in meiner Diplomarbeit beschäftigen.


Anmelden zum Antworten