wohin mit dem Thread zur Datenbeschaffung



  • Hallo Gemeinde,

    ich bekomme in einer SDI Applikation Livedaten via TCP Socket. Jetzt stellt sich mir die Frage wo ich den Arbeitsthread hinschiebe. Ich sehe drei Möglichkeiten wo mir eigentlich keine richtig gefällt
    []CDocument
    [
    ]CMainframe
    [*]CWinApp

    natürlich in die jeweiligen Ableitungen davon. CDocument finde ich nicht gut weil im eigentlichen Sinne kein Dokument da ist, sind ja Livedaten die sich laufend ändern. Und die zwei anderen nun ja, ich weiß nicht so recht ...

    Was würdet ihr empfehlen?


  • Mod

    Der Arbeitsthread ist eine Klasse die vom CDocument aus benutzt wird.
    Der Thread wird von Deinem CDocument erzeugt. Die Daten werden im CDocument aus dem Thread gesammelt und zur Anzeige im CView gebracht.

    So würde ich es sehen.



  • Wie Martin schon sagt würde ich das auch in die Dokumentenklasse schieben. Das hat ja nichts damit zu tun ob ein Dokument existiert oder nicht. Die Dokumentenklasse ist eher eine Art Datensammler. Damit kann man dann verschiedene automatische Mechanismen zum Aktualisieren der Ansicht (View) nutzen bzw. die Daten in mehreren vereschiedenen Views darstellen. Der von CDocument abgeleiteten Klasse ist es realtiv egal woher die Daten kommen und was das für Daten sind, unabhängig ob die dann noch in einer Datei gespeichert werden sollen oder eben nicht.
    Und wieso gefallen dir alle drei Klassen nicht? Bin mal auf die Begründung gespannt...



  • Dank an Euch beide,

    dann habe ich noch eine Frage.

    Den Arbeitsthread im Constuktor starten (was passiert wenn ich dort schon UpdateAllViews aufrufe) oder wo anders?


  • Mod

    Konstruktor. Schlechte Idee.

    Es gibt einige On... Methoden.
    OnNewDocument ist da wohl besser. Im Konstruktor kannst Du ja wohl schlecht UpdateAllViews aufrufen, denn je nach Tyo (SDI/MDI) gibt es noch gar keine Views.



  • Martin Richter schrieb:

    Konstruktor. Schlechte Idee.

    Dachte ich mir schon 🙂 .

    Martin Richter schrieb:

    Es gibt einige On... Methoden.
    OnNewDocument ist da wohl besser. Im Konstruktor kannst Du ja wohl schlecht UpdateAllViews aufrufen, denn je nach Tyo (SDI/MDI) gibt es noch gar keine Views.

    Danke, das hilft mir ein ganze Stück weiter.



  • Ich muß noch mal an den Thread anschließen. Ich habe meinen Arbeitsthread in OnNewDocument erstellt.

    BOOL CMyAppDoc::OnNewDocument()
    {
      if(!CDocument::OnNewDocument())
      {
        return FALSE;
      }
    
      m_threadSocked = std::thread(&CMyAppDoc::CollectFromSocket, this);
    
      return TRUE;
    }
    

    Der Thread wird auch gestartet und nimmt die Daten von dem Socket entgegen. Nur wenn ich innerhalb des Thread versuche auf die View zuzugreifen Crash das Programm.

    int CMyAppDoc::CollectFromSocket()
    {
      Sleep(30000); // zu Testzwecken eingebaut, hilft aber nicht
    
       ...  // Sockethandling
    
      if(Client.IsOpen())
      {
        UpdateAllViews(nullptr); // Crasht
        ((CMainFrame*)theApp.m_pMainWnd)->UpdateDataWnd(this); // Crasht auch, ist ein Zugriff auf ein PropertiesPane
      }
    }
    

    Das die Views noch nicht existieren kann nicht sein, dafür ist der Sleep von 30s am Anfang. Ich denke das ich mit dem Thread irgendwie nicht mehr sauber an die Views komme. Aber ich verstehe hier gerade nicht was da pasiert.


  • Mod

    Du darfst solche MFC Funktionen nicht aus einem anderen Thread ausführen.
    Die Windows Objekte sind in lokalen threadafinen Haxhmaps gespeichert.

    Du musst Dir schon eine gescheite Kommunikation übverkegen.
    Am einfachsten ist es Du postest eine Nachricht mit PostMessage und verwendest aus dem Thread kein CWnd Objekt.



  • TanteGoogle sei Dank,

    man kann von einem Thread nicht auf die Views zugreifen. Also ein Handle auf Mainframe an den Thread übergeben und mit PostMessage eine Meldung an CMainFrame schicken. Das funktioniert soweit sehr gut.

    Jetzt habe ich noch ein Memoryleak von 44Bytes. Auch wenn ich die Threadfunktion leer mache.

    int CMyAppDoc::CollectFromSocket()
    {
      while(m_stop)
        Sleep(1000);
    }
    

    Wenn ich den Threadstart aber auskommentiere ist das Leak weg. Kann mir jemand sagen was ich beim Threadstart falsch mache.

    Achso der Threadstop erfolgt in OnClosedDocument

    CMyAppDoc::OnCloseDocument()
    {
      m_stop = true; // volatile bool m_stop
      m_threadSocked.join();
    
      CDocument::OnCloseDocument();
    }
    

  • Mod

    Ich dachte std::thread ist nicht kopierbar...

    Aber evtl. hat sich das geändert.

    Ich verwende AfxBeginThread, oder CWinThread wenn ich schon mit der MFC arbeite.



  • Martin Richter schrieb:

    Ich dachte std::thread ist nicht kopierbar...

    Aber evtl. hat sich das geändert.

    Das ist wohl auch noch so, ich denke hier wird ein Move verwendet.

    Martin Richter schrieb:

    Ich verwende AfxBeginThread, oder CWinThread wenn ich schon mit der MFC arbeite.

    AfxBeginThread oder _bginthread wollte ich eigentlich los werden um mir die eigentlich "sinnlose" statische Funktion zum Start des Workers zu sparen.

    Aber ich glaube, wenn ich den Link http://connect.microsoft.com/VisualStudio/feedback/details/757212 richtig verstehe handelt es sich um einen Bug der im VS2012 nicht mehr korrigiert wird - das ist schade 😞 .

    Aber Deine Antwort legt nahe das Du was anderses als die MFC bevorzugst. Darf ich fragen was.


  • Mod

    Ich verwende meistens die MFC/CRT oder ATL...

    Die neuen Cx11 Sachen benutze ich mit Vorsicht. 😉



  • Danke Martin, das erklärt den vorletzen Beitrag auch. Ich war/bin gerade dabei auf C++11 umzustellen (soweit das geht), ich habe gerade von VS2005 auf VS2012 upgegradet. Aber schön zu sehen das ich nicht der letzte bin der mit der MFC arbeitet 🙂 .


  • Mod

    andreasgeorg schrieb:

    Aber schön zu sehen das ich nicht der letzte bin der mit der MFC arbeitet 🙂 .

    Du bist mit Sicherheit nicht der letzte. Und das liegt nicht daran, dass man mit der MFC keine gute Software entwickeln könnte.

    Nur ist mittlerweile MFC-bashing in und hipp (auch hier), insofern outet sich ja niemand mehr. Man will ja nicht als rückständig gelten.

    Bzgl. C++x11:
    Ich mag extrem viel davon, aber bei manchem frage ich mich warum ich es benutzen soll... 😉
    Manche Funktionen Klassen und anderer Libs passen oft "smoother" in die eigene Infrastruktur als das zum Teil (in meinen Augen) extrem kryptische C++x11 Zeugs.
    Aber das ist (wie so oft Geschmacksache) und muss von denen vertreten werden, die die Design Vorgaben machen 😉

    Just my 2 Cents.


Log in to reply