Fehler, wenn man UpdateAllViews() aus nem Thread heraus aufruft....???



  • Hallo,

    ich hab folgendes Problem. Ich habe mit AfxBeginThread() einen Thread gestartet, der das Document verändert, in dem es vom Document eine Methode aufruft. Innerhalb dieser Methode macht dann das CDocument ein Update auf seine Views mittels UpdateAllViews(NULL);

    Bei diesem Aufruf kriege ich dann eine Fehlermeldung, dass eine Assertion fehlgeschlagen ist in wincore.cpp, Line 1051. Beim Debuggen habe ich rausgefunden, dass es die Assertion ASSERT_VALID(pView) in CDocument::UpdateAllViews() ist...wenn man in den Code der Assertion springt, dann wird dieser Assertion das pView-Object übergeben (Variable pOb)...ich verstehe den Code zwar nicht, aber ganz am Ende dieser Assertion, wird dann der folgende Aufruf versucht: pOb->AssertValid()...In diese Methode kommt er aber irgendwie nicht - keine Ahnung wieso...pView (pOb) sind jedenfalls nicht NULL.....

    ++++++++++++++++++++++++++++++
    WEISS JEMAND,WORAN DAS LIEGEN KÖNNTE??? ICH VERMUTE, ES LIEGT DARAN, DASS DER AUSLÖSER DER GANZEN AKTION VON EINEM THREAD STAMMT...JEDENFALLS TRITT DAS PROBLEM NUR DANN AUF...
    +++++++++++++++++++++++++++++++

    Ich wäre sehr, sehr dankbar für Hilfeleistungen.....
    Bis dann.



  • Das liegt ganz einfach daran, dass man auf Fenster nur von diesem Thread zugreifen darf, welcher auch das Fenster erzeugt hat!
    Somit musst Du Deinem Fenster (oder Deiner WinApp) eine Msg schicken, der dann das Update der Views durchführt.

    PS: Hast Du auch den Zugriff auf die Daten Deines Dokumentes per CS gesichert?



  • nee, sollte ich das???...

    ...Ich hab eben mal ausprobiert, innerhalb des Threads selbst ein Lock zu setzen...das half aber alles auch nichts....

    Besten Dank für deine Antwort...ich kann mir schon vorstellen, wie das in etwa aussieht, allerdings finde ich es rel. "suboptimal", weil doch UpdateAllViews am besten in einer Methode des Documents untergebracht wäre...allerdings kann diese Methode manchmal von einem WorkerThread gerufen werden und manchmal aus dem MainThread....naja, sei's drum....



  • wayneschlegel schrieb:

    allerdings kann diese Methode manchmal von einem WorkerThread gerufen werden und manchmal aus dem MainThread....

    nein, kann es nicht. Es kann nur aus dem Window-Thread aufgerufen werden.



  • Hi Jochen, danke für deine Hilfe...

    1.)Warum kann UpdateAllViews deiner Meinung nach nur von Window-Threads gerufen werden??
    Also, das ist so: Mein Document hat ne Methode addSomeThing(), innerhalb dessen
    Daten verändert werden. Diese Methode soll (möglichst) den Aufruf
    UpdateAllViews() beinhalten, sodass sich Aufrufer von addSomeThing() nicht um
    das Updaten der Views kümmern müssen - ganz egal ob sie WorkerThreads sind oder
    aus dem MainThread kommen....Ich komme doch von jeder beliebigen Stelle im
    Program an das Document - also auch von selbsterstellten Threads...oder sehe
    ich da irgendwas falsch??

    2.) Ich hab da so eine Idee, wie ich das hinbekommen könnte. Dazu müßte ich aber
    wissen, wie man den MainThread benachrichtigen kann, dass der Workerthread
    beendet wurde (ohne, dass der MainThread blockt)...weißt du wie das geht??

    Hintergrund: Der WorkerThread, der gegenwärtig MyDocument::addSomeThing() auslöst, wird von einer anderen Klasse (die liegt ja im mainthread) gerufen. Nun könnte man es ja so machen, dass der Thread zunächst mal die Daten in Wrapperklasse schreibt (also quasi zwischenlagert)...und wenn der Thread dann zuende ist, kann doch die Wrapperklasse CMyDocument::addSomeThing() aufrufen...dann müßte doch wieder alles passen....



  • wayneschlegel schrieb:

    1.)Warum kann UpdateAllViews deiner Meinung nach nur von Window-Threads gerufen werden??
    Also, das ist so: Mein Document hat ne Methode addSomeThing(), innerhalb dessen
    Daten verändert werden. Diese Methode soll (möglichst) den Aufruf
    UpdateAllViews() beinhalten, sodass sich Aufrufer von addSomeThing() nicht um
    das Updaten der Views kümmern müssen - ganz egal ob sie WorkerThreads sind oder
    aus dem MainThread kommen....Ich komme doch von jeder beliebigen Stelle im
    Program an das Document - also auch von selbsterstellten Threads...oder sehe
    ich da irgendwas falsch??

    Man kann eigentlich fast alles programmieren... ob es mit dem zugrindeliegende Model auch Sinnvoll ist ist ja was anderes.

    wayneschlegel schrieb:

    2.) Ich hab da so eine Idee, wie ich das hinbekommen könnte. Dazu müßte ich aber
    wissen, wie man den MainThread benachrichtigen kann, dass der Workerthread
    beendet wurde (ohne, dass der MainThread blockt)...weißt du wie das geht??

    SendMessage/PostMessage mit WM_APP + x

    wayneschlegel schrieb:

    Hintergrund: Der WorkerThread, der gegenwärtig MyDocument::addSomeThing() auslöst, wird von einer anderen Klasse (die liegt ja im mainthread) gerufen. Nun könnte man es ja so machen, dass der Thread zunächst mal die Daten in Wrapperklasse schreibt (also quasi zwischenlagert)...und wenn der Thread dann zuende ist, kann doch die Wrapperklasse CMyDocument::addSomeThing() aufrufen...dann müßte doch wieder alles passen....

    Du musst halt sicherstellen, dass die beiden Threads *nie* gleichzeitig Daten verändern können.



  • Hi Jochen,

    nochmals danke...für SendMessage/PostMessage brauche ich doch aber meines Wissens den HWND auf das MainWindow, sodass dort dann auch die OnMessage()-Methode für die Nachricht platziert wird, ODER???...Eigentlich will ich ja nicht das MainWindow benachrichtigen, sondern lediglich die Klasse, die den Workerthread gestartet hat...ich hab mir mal eben CEvent() angeschaut....aber ich weiß nicht so recht, ob das für diese Zwecke geeignet ist...

    so wie ich das verstehe, würde der Thread (wenn er fertig ist) ein Event setzen und die Klasse, die den Thread gesartet hat (und über dessen Beendigung benachrichtigt werden will), muß dann WaitForSingleEvent() rufen...das ist allerdings dann wieder blockierend.....

    Bis dann...


Anmelden zum Antworten