Announcement

Collapse
No announcement yet.

Probleme beim Aufruf von Objektmethode in Thread

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

  • Probleme beim Aufruf von Objektmethode in Thread

    Hallo,

    für ein Programm das unter anderem mittels HTTP-Get Seiten anfordert, möchte ich für eben diese Aufrufe eigene Threads erstellen, da sie den Rest vom Programm blockieren.

    Beim Benutzen der Klasse TThread hatte ich das Problem das mein Programm sich nach dem Erstellen des Threads komplett aufhängte.

    Hier nun mein Versuch über die WinAPI :

    var ThreadIDWord;
    Auktion:TAuction;
    .
    .
    .

    Auktion:=Auktionen.items[i]; //Auktionen ist eine Liste mit Objekten.
    ThreadHandle:=CreateThread(nil, 0, @TAuction.Refresh ,Auktion, 0, ThreadID);

    Dies hier funktioniert soweit, zumindest wird im Debugger auch die Methode Refresh aufgerufen, allerdings sind die Variablen nicht initialisiert (nicht verfügbarer Wert). Ich vermute es liegt daran das ich ja nicht die Methode der Instanz sondern die der Klasse übergeben habe. Wenn ich allerdings die Adresse der Methode der Instanz übergeben will kommt die Fehlermeldung "Variable erforderlich", der Cursor steht allerdings schon bei dem nächsten Argument, dort wo oben "Auktion" steht.

    Meine Frage also :

    Wie lautet der syntaktisch richtige Aufruf um einen Thread zu erzeugen in dem eine Klassenmethode abgearbeitet wird ?

    Vielen Dank

  • #2
    Nutze TThread, er mach nichts anderes als das was Du mit API erledigen würdest.<br>

    CreateThread() benötigt eine Thread Function die etwa so deklariert ist: function MyThreadProc(Param: Integer): Integer; <b>stdcall</b>;<br>
    Man kann diese in eine Object Methode mappen, etwa so:

    <pre>

    type
    TMyObject = class
    function ThreadProc: Integer; stdcall;
    end;

    </pre>

    CreateThread() muß als Parameter auf die Instance des entspr. Objectes zeigen. Dies hast Du schon korrekter weise gemacht.<br>
    In der .ThreadProc; sollte unbedingt ein try except Handler rein, also:

    <pre>

    function TMyObject.ThreadProc: Integer; stdcall;
    begin
    try
    Result := 0;
    // nur hier aktiven code
    except
    // <- hier NIMEALS raise o.ö.
    end;
    end;<br>

    </pre>

    Hage

    Comment


    • #3
      Ich würde ja gern TThread nutzen, allerdings komme ich damit nicht so weit wie mit der API-Funktion, das Programm stürzt nach erstellen des Threads ab. Wenn ich vor Ausführung der Execute-Funktion dem Thread-Objekt noch über eine Eigenschaft das entsprechende Auktionsobjekt zuweisen wollte stürzte auch die Delphi-IDE mit ab...Das war der Grund warum ich das ganze über API versucht habe. Und das gefällt mir nun schon mal grundsätzlich besser, da ich keine Abstürze habe und nach hinzufügen von stdcall; zur Funktionsdeklaration wird auch die richtige Methode aufgerufen.

      Vielen Dank für Deine Antwort, Du hast mit sehr geholfen, da wäre ich nämlich _nie_ draufgekommen...

      Nochmal zum Verständnis : Warum sollte ich in meinem Fall TThread nutzen ? Zwischen den Threads muss nichts synchronisiert werden oder ähnliches. Allerdings wird ein Eintrag in einem Listview auf der Hauptform verändert, soweit ich das verstanden habe ist das nicht Threadsicher,d.h. wenn ich z.b. in dem Moment wo der Thread auf das Item zugreift dieses lösche, dann knallts... ? Wie kann ich hier mit Hilfe von Winapi-Funktionen Abhilfe schaffen ??

      mf

      Comment


      • #4
        Das ist das "unschöne" an der VCL. Die VCL kapselt die Windows-ListBox als Komponente. Wird z.B. ein Eintrag aus der Liste entfernt so rufen wir im Source den VCL Code auf der dann per Messages die Windows-ListBox Fensterfunktion aufruft. Dieser SendMessage() Aufruf ist threadsicher, aber eben nicht der VCL Aufruf. Ich würde also aus Deinem Thread heraus SendMessage(LBM_ADDSTRING/LBM_DELETESTRING) benutzen. Durch das SendMessage() entsteht der gleiche Effekt wie ein TThread.Synchronize(), d.h. der Thread wartet und synchronisiert.<br>

        TThread würde ich deshalb nutzen weil es ein Standard-weg der Delphi Programmierung ist. Wird mit TThread gearbeitet so hat man 1. eine Programmierung die durch andere Coder verstanden wird und 2. eine gewisse Plattformunabhängigkeit und 3. sollte das Exceptionhandling im TThread "sauber" erledigt sein.<br>

        In deinem Beispiel also:

        <pre>
        type
        TMyThread = class(TThread)
        private
        FListBoxHandle: hWnd;
        protected
        procedure Execute; override;
        public
        constructor Create(AListBoxHandle: hWnd);
        end;<br>

        procedure TMyThread.Execute;
        var
        S: String;
        begin
        try
        while not Terminated do
        begin
        .... tue sonst was mit S
        if not IsWindow(FListBoxHandle) then Break
        else SendMessage(FListBoxHandle, LBW_ADDSTRING, PChar(S), Length(S));
        end;
        except
        end;
        end;<br>

        constructor TMyThread.Create(AListBoxHandle: hWnd);
        begin
        inherited Create(True);
        FreeOnTerminate := True;
        FListBoxHandle := AListBoxHandle;
        Resume;
        end;<br>

        </pre>

        Gruß Hage

        Comment


        • #5
          Wunderbar, jetzt klappts auch mit der TThread-Klasse. Ich würde zwar schwören das ich alles genau so gemacht hatte, aber etwas werde ich wohl falsch gemacht haben müssen.

          Jetzt funktioniert es auch sauber, bei der WinAPI-Version hatte ich Probleme, das seltsamerweise plötzlich der Socket nicht mehr verbunden war.

          Was mich allerdings wundert ist, das ich 2 Threads mehr habe als erwartet (zumindest laut Taskmanager). Werden die von Delphi erzeugt um alle Treads zu managen oder woher kommen diese ?

          Ansonsten nochmal Vielen Dank, ich weis nicht ob ich das allein hinbekommen hätte

          mf

          Comment


          • #6
            Deine Sockets werden wohl diese Thread anlegen.<br&gt

            Comment

            Working...
            X