lparam und MSG



  • Moin!

    Ich glaube ich habe zu schlecht geschlafen... Ich krieg heut echt NULL auf die Reihe. (Man bemerke die kleine Anspielung :D)

    Also mein Problem ist:

    Ich habe diverse Threads.

    Thread A, ein Formular und einen Thread B.

    Thread A rennt.
    Formular rennt.
    Thread B schläft mit GetMessage.

    Folgendes wird passieren:

    Thread A feuert mit PostThreadMessage eine Nachricht an B.
    B wacht auf und führt mittels Synchronize im Formular was aus.

    Grund für diese Variante ist einfach zEitersparnis. Ich hab gemessen. Wenn ich das so mach muss ich nicht im Formular alles mit Mutexen vollknallen.
    Bzw. hab ich noch ned nachgeschaut wie ich Nachrichten an einen TForm Thread schicke.

    Egal. Das Ganze mach ich eben mit MSG, PostThreadMessage und GetMessage. also API Funktionalität.

    Aber nun zu meinem Problem. Ich muss eine Datenvariable rüberbringen.

    int* zahl;
    PostThreadMessage(x,x,x,zahl);

    GetMEssage(MSG,,,);

    etc blabla is ja klar...

    So und dann

    int* zahlparameter = (int*) Msg.lparam;

    Soweit so gut... Is ja OK mit Pointern...

    ABER in der Zwischenzeit ist A ja weiter geflitzt. Also kann sich der Inhalt des Zeigers 5x geändert haben...

    Ich raffs aber grad ned wie ich ne stink normale Variable übergeb oder so. Normale Parameterübergabe macht ja ne Kopie...

    Handelt sich bürgiends nicht um ne int.... das war nur ein Bleistift.



  • Diese ganzen Personifikationen ... 😃 .

    Also bei PostThreadMessage musst Du erstmal darauf achten, dass die Nachricht gesendet wird und anschließend nicht gewartet wird, bis diese bearbeitet wird. Die Funktion retuniert sofort! Das ist wichtig, wenn Du Zeiger auf Bereiche übergibst, die nur im Thread konsistent sind.
    Bzw. des Änderns der Daten, ... da musst Du einfach sychronisieren, evtl. ist es schneller ein neues unabhängiges Synch-Objekt zu erstellen (Critical-Section), damit das ganze etwas schneller läuft.



  • CodeFinder schrieb:

    Diese ganzen Personifikationen ... 😃 .

    Que?

    Also bei PostThreadMessage musst Du erstmal darauf achten, dass die Nachricht gesendet wird und anschließend nicht gewartet wird, bis diese bearbeitet wird. Die Funktion retuniert sofort! Das ist wichtig, wenn Du Zeiger auf Bereiche übergibst, die nur im Thread konsistent sind.

    Wenn du damit sagen willst, daß es mit Pointern als Parameter Probleme gibt... GENAU das is eine Frage wie ich drumrum komm... Denn Thread A WIRD weiter laufen und er WIRD den Inhalt des Zeigers ändern. Deswegen überhaupt mein Post.

    Bzw. des Änderns der Daten, ... da musst Du einfach sychronisieren, evtl. ist es schneller ein neues unabhängiges Synch-Objekt zu erstellen (Critical-Section), damit das ganze etwas schneller läuft.

    Unabhängig in welchem Sinne? Also Die Verwendung einer TCriticalSection bzw. eines TSynchroObjects (Wobei wir aus der Api rausflutschen mit den beiden Klassen.... Aber die sind ja auch nur Implementierungen der API...)
    Hat mich mehrere Millisekunden gekostet! Denn da meine Elemente auf die ich zugreife Teil des Formulars sind, werde ich jeden achso kleinen Zugriff sichern müssen. Was mich ausbremst... Also wenn ich einen Thread nur Posten lasse, wobei Thread B default Werte im Formular schreibt, brauch ich bis zu 7ms... Mach ichs über Synchronize komplett ohne diverse Objekte, 1ms, wenn überhaupt. Denn das Anhalten des Formular Threads ist schneller als jedesmal Lock und Unlock... Ich habs ausgemessen....

    Sinn ist eben, daß ich von irgendwoher mehrere Strings in das Formular kriegen muss und dort in ein Array bzw. ListView packen. Das Formular sichert aber auch das Array bzw. das ListView... Also greift es auch lesend und schriebend zu.

    Sprich ich müsste ohne Synchronize jeeeeden Zugriff absichern. Und das frisst.



  • Shogun schrieb:

    Que?

    ➡

    Thread A rennt.
    Formular rennt.
    Thread B schläft mit GetMessage.

    Shogun schrieb:

    Wenn du damit sagen willst, daß es mit Pointern als Parameter Probleme gibt... GENAU das is eine Frage wie ich drumrum komm... Denn Thread A WIRD weiter laufen und er WIRD den Inhalt des Zeigers ändern. Deswegen überhaupt mein Post.

    Es muss nicht grundsätzlich Probleme geben. Es geht. Man muss eben nur dafür sorgen, dass der adressierte Bereich auch gültig ist/bleibt. Wenn er sich ändert *MUSST* Du synchronisieren, da geht kein Weg dran vorbei.

    Shogun schrieb:

    Sprich ich müsste ohne Synchronize jeeeeden Zugriff absichern. Und das frisst.

    Da kommst Du nicht drum herum... das ist der Nachteil von Multithreading.



  • Ausser ich krich irgendwie meine PArameter rüber ohne Zeiger zu verwenden...



  • Bei primitiven Typen ist das auch möglich, aber deren Kapazitäten reichen ja meistens nicht :p .



  • Mhm leider...Ich müsste so 5-6 Strings rüberkriegen. *argh*

    Evtl. Mach ichs anders.
    Ich verwende eine Critical Section in B. Locke die von A aus. Rufe eine Fire Funktion in B auf, die erst die Membervariablen setzt und dann Synchronize aufruft. Dann mache ich mein Unlock...


  • Mod

    Evtl. ist es performanter. Einfach eine Queue zu verwenden, in die die Daten angehängt werden undnur einen PostMessage für die Benachrichtigung. Die Queue wird dann über eine CrticalSection abgesichert, von beiden Threads aus natürlich.



  • Hmmm... Ne List aus der STL als FIFO benutzen meinst du?

    Rein Theoretisch kommen die sich doch nicht in die Quere, so daß ich das nichtmal absichern müsste oder?

    Das Problem ist: Es gibt mehrererererere Thread A. Die das alle wollen.

    Wenn ich doch eine list mache. Mit jedem Post Message schnappt der sich das Erste Element der Liste, liesst es und löscht es. Thread A kann doch dann fröhlich append mit der Liste machen oder? Er hängt ja nur hintendran.

    Oops... Ich nehms zurück... Wenn da zwei A gleichzeitig rein wollen gibts gehakel. Also doch absichern. Aber das mit der Fifo Liste als Queue ist ne Klasse Idee...

    B mit ner Critical Section sichern. In B eine list einbauen. Und B Nimmt sich bei jedem PostThreadMessage das Letzte Element.

    Das Senden funktioniert dann so:

    lock
    list.append
    postthreadmessage
    unlock

    Senden im Lock, damit nicht ein andrer Thread reinpfuscht.

    DAs ist so wie du es meinst oder?


  • Mod

    Mit Sicherheit kostet dieses Verfahren weitaus weniger Performance als ein SendMessage. Die Critical Section ist nur im Konflikt langsam!
    Alle anderen Mechanismen wie SendMessage über Threadgrenzen hinweg sind weitaus extremer.
    Ich wundere mich jedesmal, das solche Konstrukte gebastelt werden.

    Noch effektiver ist wenn nicht mal die Message Queue verwendet wird sondern einfach ein Event. Oder Du kannst den lesenden Thread sogar per Timer einfach zyklisch nach sehen lassen ob was zu tun ist.



  • Ich dachte bisher das Pollen wäre langsamer?

    Ja per Event hab ich auch überlegt. Ich traue den Message Queues irgendwie nicht so ganz...

    Allerdings brauche ich doch dann die Liste nicht mehr oder?

    A:
    lock
    set list item
    raise event
    unlock

    B:
    waitfor(event)
    lock
    read list item
    delete list item
    reset event
    unlock

    Diese Variante blockiert doch die Liste sowieso, so daß nur ein Element drin landen kann.
    Ausser in genau der Zeit zwischen A unlock und B lock flitzt ein anderer A Thread da rein und macht schnell ein append. Das wäre natürlich ein Grund für die Liste.

    Brauche ich da überhaupt eine Liste? Reicht da nicht ein Objekt in B, statt einer Liste?

    Alternative wäre dann

    A:
    lock
    setappendraise event
    unlock

    B:
    waitfor(event)
    lock
    hwile (listengrüße nicht erreicht)
    read list item
    delete list item
    reset event
    unlock

    EDIT: Gehört das nicht so langsam in Rund um die Programmierung?`Ist ja eine Grundlagenfrage, die sich überall stellt. Egal welche Bibliothek...


Anmelden zum Antworten