Announcement

Collapse
No announcement yet.

Aus der Execute eines Threads eine Botschaft verschicken ohne auf die Rückkehr zu warten

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Aus der Execute eines Threads eine Botschaft verschicken ohne auf die Rückkehr zu warten

    <font face="Arial">
    Hallo<br>
    wie&nbsp;kann&nbsp;ich&nbsp;aus&nbsp;der&nbsp;Exec ute&nbsp;eines&nbsp;Threads<br>
    eine&nbsp;Botschaft&nbsp;verschicken&nbsp;ohne&nbs p;auf&nbsp;die&nbsp;<br>
    R&uuml;ckkehr&nbsp;zu&nbsp;warten.&nbsp;Diese&nbsp ;Botschaft&nbsp;soll<br>
    an&nbsp;den&nbsp;Thread&nbsp;selber&nbsp;gehen&nbs p;aber&nbsp;nicht&nbsp;in<br>
    der&nbsp;Execute&nbsp;mit&nbsp;GetMessage&nbsp;abg efangen&nbsp;<br>
    werden.&nbsp;Ich&nbsp;m&ouml;chte&nbsp;nur&nbsp;ei nen&nbsp;Vorgang&nbsp;<br>
    starten&nbsp;der&nbsp;sich&nbsp;selber&nbsp;beende t.<br>
    <br>
    Viele&nbsp;Gr&uuml;&szlig;e<br>
    Harald&nbsp;Binder<br>
    </font>

  • #2
    Dieser Vorgang soll aber im selben Thread Context laufen ?<br>

    Gruß Hage

    Comment


    • #3
      <font face="Arial">
      Hallo&nbsp;Hagen<br>
      Ja&nbsp;das&nbsp;sollte&nbsp;er.&nbsp;<br>
      <br>
      Gru&szlig;<br>
      Harald&nbsp;Binder<br>
      </font&gt

      Comment


      • #4
        Hm, nochmal damit ichs begreife: der Thread soll diese Funktion nur auslösen, weiterlaufen und erst später diese Funktion wirklich abarbeiten. Das einfachste Mittel wäre eine Boolean Variable in der .Execute Loop auf True zu setzen. Am Ende dieser Loop steht dann der Aufruf der eigentlichen Funktion wenn das Booleanflag True ist.<br>
        Alles andere macht in meinen Augen keinen Sinn, da egal ob Thread oder MainThread, das Verfahren wie bei PostMessage() auch nur eine zeitverzögerte sequentielle Abarbeitung des Programmcodes darstellt.<br>
        Ansonsten bliebt nur innerhalb des Threads einen neuen Thread zu starten der "parallel" die Funktion ausführt.

        Gruß Hage

        Comment


        • #5
          <font face="Arial">
          Hallo&nbsp;Hagen,<br>
          ich&nbsp;m&ouml;chte&nbsp;mit&nbsp;GetQueuedComple tionStatus&nbsp;und&nbsp;ReadDirectoryChanges&nbsp ;einen<br>
          Ordner&nbsp;&uuml;berwachen.&nbsp;In&nbsp;der&nbsp ;Execute&nbsp;sollen&nbsp;die&nbsp;Events&nbsp;in& nbsp;eine&nbsp;ActionList<br>
          geschrieben&nbsp;werden.&nbsp;Der&nbsp;Grund&nbsp; ist&nbsp;wenn&nbsp;ich&nbsp;mich&nbsp;zu&nbsp;lang e&nbsp;im&nbsp;Loop&nbsp;<br>
          aufhalte&nbsp;k&ouml;nnen&nbsp;mir&nbsp;Events&nbs p;verloren&nbsp;gehen.&nbsp;Das&nbsp;schreiben&nbs p;der&nbsp;ActionList<br>
          geht&nbsp;schneller&nbsp;als&nbsp;das&nbsp;was&nbs p;ich&nbsp;mit&nbsp;diesen&nbsp;Events&nbsp;machen &nbsp;mu&szlig;.&nbsp;Also&nbsp;soll&nbsp;<br>
          der&nbsp;ganze&nbsp;Kram&nbsp;in&nbsp;eine&nbsp;Li ste&nbsp;geh&auml;mmert&nbsp;werden&nbsp;und&nbsp; au&szlig;erhalb&nbsp;des&nbsp;Loops<br>
          abgearbeitet&nbsp;werden.&nbsp;Das&nbsp;geht&nbsp; allerdings&nbsp;nur&nbsp;wenn&nbsp;ich&nbsp;nicht& nbsp;auf&nbsp;die&nbsp;<br>
          R&uuml;ckkehr&nbsp;der&nbsp;Message&nbsp;waren&nbs p;mu&szlig;.&nbsp;Ich&nbsp;hoffe&nbsp;es&nbsp;ist& nbsp;jetzt&nbsp;verst&auml;ndlich<br>
          geworden.<br>
          <br>
          Das&nbsp;ist&nbsp;der&nbsp;Anfang&nbsp;der&nbsp;pr ocedure&nbsp;die&nbsp;angesto&szlig;en&nbsp;werden &nbsp;soll.<br>
          <br>
          procedure&nbsp;TRingStorageThr.DoAddVideo;<br>
          var<br>
          &nbsp;&nbsp;Action&nbsp;:&nbsp;Integer;<br>
          begin<br>
          &nbsp;&nbsp;if&nbsp;AddList.Count&nbsp;&gt;&nbsp;0 &nbsp;then&nbsp;while&nbsp;AddList.count&nbsp;&gt; &nbsp;0&nbsp;do&nbsp;begin<br>
          &nbsp;&nbsp;&nbsp;&nbsp;Action&nbsp;:=&nbsp;&nbsp; StrToInt(AddList.Strings[0][1]);<br>
          &nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;Action&nbsp;of<b r>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE_ACTION_AD DED:&nbsp;begin<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE_ACTION_RE MOVED:&nbsp;begin<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE_ACTION_MO DIFIED:&nbsp;begin<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE_ACTION_RE NAMED_OLD_NAME:&nbsp;begin<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE_ACTION_RE NAMED_NEW_NAME:&nbsp;begin<br>
          &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end;<br>
          &nbsp;&nbsp;&nbsp;&nbsp;end;<br>
          &nbsp;&nbsp;end;<br>
          end;<br>
          <br>
          Danke&nbsp;schon&nbsp;mal<br>
          <br>
          Viele&nbsp;Gr&uuml;&szlig;e<br>
          Harald&nbsp;Binder<br>
          </font&gt

          Comment


          • #6
            Also dann musst du mit zwei Threads arbeiten, wobei einer dein Überwachungsthread ist und der andere zB. der Mainthread der Applikation.

            Im Überwachungsthread wartest du auf die Events und füllst eine neue Liste, danach wird mit PostMessage() der Mainthread informiert. Die Event-Liste sollte als Object in einer Liste hinzugefügt werden, per Locking, die dann der Mainthread nach Empfang der PostMessage() ausließt.<br>

            Aber! wie kommst du darauf das dir Events verloren gehen ?? Das OS buffert die ja auch zwischen.

            Gruß Hage

            Comment


            • #7
              <font face="Arial">
              Hi&nbsp;Hagen,<br>
              dann&nbsp;wird&nbsp;mir&nbsp;ja&nbsp;wohl&nbsp;nic ht&nbsp;anderes&nbsp;&uuml;brigbleiben&nbsp;als&nb sp;einen<br>
              zus&auml;tzlichen&nbsp;Thread&nbsp;damit&nbsp;zu&n bsp;beauftragen.&nbsp;<br>
              <br>
              Meinst&nbsp;Du&nbsp;die&nbsp;Events&nbsp;vom&nbsp; PostMessage??&nbsp;Die&nbsp;meine&nbsp;ich&nbsp;ni cht.&nbsp;<br>
              Ich&nbsp;meine&nbsp;das&nbsp;die&nbsp;&Auml;nderun g&nbsp;eines&nbsp;Ordners(Event)&nbsp;nicht&nbsp;i mmer<br>
              ankommen.&nbsp;Ich&nbsp;kann&nbsp;das&nbsp;nur&nbs p;sehr&nbsp;schwer&nbsp;nachvollziehen&nbsp;weil<b r>
              ich&nbsp;in&nbsp;dem&nbsp;Ordnersystem&nbsp;im&nbs p;Moment&nbsp;mit&nbsp;fast&nbsp;100000&nbsp;Video s<br>
              arbeite.&nbsp;Und&nbsp;das&nbsp;sind&nbsp;noch&nbs p;sehr&nbsp;wenig.&nbsp;Eine&nbsp;ScanRoutine&nbsp ;mit&nbsp;<br>
              FindFirst/FindNext&nbsp;dauert&nbsp;immer&nbsp;ewig&nbsp;lan ge.&nbsp;Besonders&nbsp;dann<br>
              wenn&nbsp;das&nbsp;System&nbsp;neu&nbsp;gestartet& nbsp;wurde.&nbsp;Au&szlig;erdem&nbsp;habe&nbsp;ich &nbsp;<br>
              festgestellt&nbsp;das&nbsp;manchmal&nbsp;hinter&nb sp;dem&nbsp;Filenamen&nbsp;Datenm&uuml;ll&nbsp;ste ht,&nbsp;<br>
              obwohl&nbsp;ich&nbsp;wie&nbsp;folgt&nbsp;auslese.< br>
              <br>
              FileName&nbsp;:=&nbsp;Trim(WideCharLenToString(@(F ileOpNotification^.FileName),<br>
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&n bsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&n bsp;&nbsp;&nbsp;&nbsp;FileOpNotification^.FileName Length));<br>
              <br>
              Das&nbsp;bedeutet&nbsp;das&nbsp;FileNameLength&nbs p;nicht&nbsp;immer&nbsp;stimmt.&nbsp;Oder&nbsp;ich &nbsp;habe&nbsp;ein&nbsp;<br>
              Zeigerproblem.&nbsp;Durch&nbsp;den&nbsp;Datenm&uum l;ll&nbsp;dahinter&nbsp;wird&nbsp;der&nbsp;File&nb sp;nicht&nbsp;als&nbsp;<br>
              Multieye-Video&nbsp;erkannt.&nbsp;<br>
              <br>
              Sch&ouml;nen&nbsp;Dank&nbsp;f&uuml;r&nbsp;deine&nb sp;wie&nbsp;immer&nbsp;gute&nbsp;Hilfe.<br>
              <br>
              Viele&nbsp;Gr&uuml;&szlig;e<br>
              Harald&nbsp;Binder<br>
              </font&gt

              Comment


              • #8
                Ich das FileNotify Event. Sobald ein solches in einem WatchThread reinkommt, wird es als Liste erzeugt und per Locking in eine globale Liste angefügt. Nach dem Anfügen wird per PostMessage eine Message zB. an MainForm abgesetzt das sich an der Liste was geändert hat. Natürlich kannst auch mit MakeObjectInstance() eine eigene Fensterprocedure für den Thread registrieren. Dies läuft dann im MainThread wird aber zusammen mit dem Thread erzeugt und zerstört.

                Etwa so:
                <pre>
                type
                TWatchThread = class(TThread)
                private
                FWnd: hWnd;
                FList: TList;
                FThreadList: TList;
                FLock: TRTLCriticalSection;
                FOnChange: TNotifyEvent;
                procedure WndProc(var Msg: TMessage);
                protected
                procedure Execute; override;
                public
                procedure Lock;
                procedure Unlock;
                contructor Create;
                destructor Destroy; override;
                published
                property List: TList read FList;
                property OnChange: TNotifyEvent read FOnChange write FOnChange;
                end;<br>

                procedure TWatchThread.WndProc(var Msg: TMessage);
                begin
                if Msg.Msg = wm_User then
                try
                Lock;
                FList.AddObjects(FThreadList);
                FThreadList.Clear;
                finally
                Unlock;
                if Assigned(FOnChange) then
                FOnChange(Self);
                end else
                with Msg do
                Result := CalldefWndProc(FWnd, Msg, wParam, lParam);
                end;<br>

                procedure TWatchThread.Execute;
                begin
                try
                while not Terminated do
                if WaitForMultipleObjects() = WAIT_OBJECT_0 then
                try
                Lock;
                ... Get Notify's
                FThreadList.Add();
                finally
                Unlock;
                PostMessage(FWnd, wm_User, 0, 0);
                end else Terminate;
                except
                end;
                end;<br>

                procedure TWatchThread.Lock;
                begin
                EnterCtricialSection(FLock);
                end;<br>

                procedure TWatchThread.Unlock;
                begin
                LeaveCtricialSection(FLock);
                end;<br>

                contructor TWatchThread.Create;
                begin
                inherted Create(True);
                InitializeCriticialSection(FLock);
                FList := TList.Create;
                FThreadList := TList.Create;
                FWnd := MakeObjectInstance(WndProc);
                Resume;
                end;<br>

                destructor TWatchThread.Destroy;
                begin
                inherited Destroy;
                DestroyWnd(FWnd);
                FreeObjectInstance(WndProc);
                FList.Free;
                FThreadList.Free;
                DeleteCriticalSection(FLock);
                end;<br>

                </pre>

                Gruß Hage

                Comment


                • #9
                  <font face="Arial">
                  Hallo&nbsp;Hagen,<br>
                  Danke&nbsp;f&uuml;r&nbsp;Deine&nbsp;Hilfe.<br>
                  <br>
                  Aber&nbsp;ich&nbsp;habe&nbsp;Probleme&nbsp;die&nbs p;eigene&nbsp;Fensterprocedure&nbsp;f&uuml;r&nbsp; den&nbsp;Thread&nbsp;zu&nbsp;registrieren.<br>
                  <br>
                  FWnd&nbsp;:=&nbsp;MakeObjectInstance(WndProc);&nbs p;&gt;&gt;&nbsp;Fehler&nbsp;Inkompatible&nbsp;Type n:&nbsp;HWND&nbsp;und&nbsp;Pointer<br>
                  <br>
                  DestroyWnd(FWnd);&nbsp;&gt;&gt;&nbsp;Fehler&nbsp;U ndefinierter&nbsp;Bezeichner&nbsp;DestroyWnd&nbsp; (Unit&nbsp;Controls&nbsp;ist&nbsp;eingebunden)<br>
                  <br>
                  FreeObjectInstance(WndProc);&nbsp;&gt;&gt;&nbsp;Ni cht&nbsp;gen&uuml;gend&nbsp;wirkliche&nbsp;Paramet er<br>
                  <br>
                  W&uuml;rdest&nbsp;Du&nbsp;mir&nbsp;ein&nbsp;Beispi el&nbsp;erstellen&nbsp;welches&nbsp;funktioniert.& nbsp;Ich&nbsp;meine&nbsp;nur&nbsp;das&nbsp;erzeuge n&nbsp;der<br>
                  eigene&nbsp;Fensterprocedure.&nbsp;Ich&nbsp;verste hen&nbsp;den&nbsp;ganzen&nbsp;Kram&nbsp;n&auml;mli ch&nbsp;nicht.<br>
                  <br>
                  Das&nbsp;w&auml;hre&nbsp;sehr&nbsp;nett&nbsp;von&n bsp;Dir.<br>
                  <br>
                  Viele&nbsp;Gr&uuml;&szlig;e<br>
                  Harald&nbsp;Binder<br>
                  </font&gt

                  Comment


                  • #10
                    Scheiße ich habe da was durcheinander gebracht.
                    Es muß FWnd := AllocateHWnd(WndProc); und DeallocateHWnd(FWnd); heissen.

                    <pre>
                    contructor TWatchThread.Create;
                    begin
                    inherted Create(True);
                    InitializeCriticialSection(FLock);
                    FList := TList.Create;
                    FThreadList := TList.Create;
                    FWnd := AllocateHWnd(WndProc);
                    Resume;
                    end; <br>

                    destructor TWatchThread.Destroy;
                    begin
                    inherited Destroy;
                    DeallocateHWnd(FWnd);
                    FList.Free;
                    FThreadList.Free;
                    DeleteCriticalSection(FLock);
                    end;

                    </pre>

                    Aus DestroyWnd() wird richtigerweise DestroyWindow(). An Hand meines obigen Beispiels sieht man sehr schön das ich im Grunde ein Trial&Error Coder bin. Nicht jede Funktion ist mir exakt geläufig, sondern nur die Information das da irgendwas existiert mit so einem ähnlichem Namen. Tja, das ist halt das Problem wenn man frei aus dem Gedächtnis codet ohne zu testen. Allerdings, Harald, es lauffähig zu bekommen ist ja deine Aufgabe

                    Gruß Hage

                    Comment


                    • #11
                      Und noch eines drauf:

                      <pre>
                      procedure TWatchThread.WndProc(var Msg: TMessage);
                      begin
                      if Msg.Msg = wm_User then
                      try
                      Lock;
                      FList.AddObjects(FThreadList);
                      FThreadList.Clear;
                      finally
                      Unlock;
                      if Assigned(FOnChange) then
                      FOnChange(Self);
                      end else
                      with Msg do
                      Result := DefWindowProc(FWnd, Msg, wParam, lParam);
                      end;
                      </pre>

                      Also DefWindowProc() statt CallDefWndProc().

                      Gruß Hage

                      Comment


                      • #12
                        So, AllocateHWnd(WndMethod) erzeugt ein Window Fenster mit der Klasse "TPUtilWindow" und ordnet WndMethod als Fensterfunktion zu. Zb. TTimer/Thread-Synchronize (bis D5) usw. funktionieren auf diesem Wege. DeallocateHWnd() zerstört das Fensterhandle und gibt den Stub für WndMethod frei. Dieser Stub wird mit MakeObjectInstance(WndMethod) erzeugt udn mit FreeObjectInstance() wieder freigegeben. Einfach mal in Forms.pas (D5) und ExtCtrls.pas reinschauen.

                        Gruß Hage

                        Comment

                        Working...
                        X