2010-11-23 19 views
2

Also, mein Ziel ist es, eine Funktion in einem anderen Thread zu starten. Außerdem benötige ich Zugriff auf andere vcl-Komponenten von neuem Thread. Hier ist mein Code so weit:Zugriff auf vcl-Komponente im Thread! Delphi

procedure TForm1.StartButtonClick(Sender: TObject); 
var 
thread1: integer; 
id1: longword; 
begin 
    thread1 := beginthread(nil,0,Addr(Tform1.fetchingdata),nil,0,id1); 
    closehandle(thread1); 
end; 

procedure TForm1.FetchingData; 
var 
    ... 
begin 
    Idhttp1.IOHandler := IdSSLIOHandlerSocketOpenSSL1; //<- error 
    idhttp1.Request.ContentType := 'application/x-www-form-urlencoded'; 

mein Programm hängt und ich erhalte Fehler: Ausnahme EAccessViolation in Modul my.exe bei 00154E53. Zugriffsverletzung bei Adresse 00554E53 in Modul 'my.exe'. Lesen Sie von Adresse 00000398.

Vielen Dank im Voraus.

Antwort

9

Die Ursache des AV ist, dass Sie die Adresse einer TForm Methode an eine Funktion übergeben, die eine TThreadFunc erwartet (siehe documentation of System.BeginThread()). Die Verwendung von Addr() ist eine gute Möglichkeit, den Compiler daran zu hindern, auf Ihre Fehler hinzuweisen.

Sie müssten stattdessen eine Wrapperfunktion mit der richtigen Signatur schreiben, die Formularinstanz als Parameter übergeben und die Methode für das Formular von dieser Funktion aus aufrufen.

Aber gehen Sie nicht dorthin, entweder Ihren Code als Nachkomme TThread schreiben, oder (vorzugsweise) verwenden, um eine höhere Ebene Wrapper wie AsyncCalls oder Omni Thread Library. Und stellen Sie sicher, dass Sie nicht auf VCL-Komponenten im Hauptthread zugreifen, erstellen Sie und geben Sie diejenigen frei, die Sie in Ihrem Arbeitsthread benötigen.

5

Auf die VCL (Gui-Komponenten) kann nur vom Hauptthread zugegriffen werden. Andere Threads benötigen den Haupt-Thread für den Zugriff auf die VCL.

+1

und die einfache Möglichkeit, dies zu erreichen, die sekundären Threads WM_USER Nachrichten veröffentlichen und den Haupt-Thread, um sie zu reagieren. In Ihrem Fall können Sie jedoch den gleichen Effekt erzielen, wenn Sie das indy TidAntiFreeze-Objekt verwenden. Lies 'http: // stackoverflow.com/questions/37185/whats-the-idiomatisch-zu-tun-async-socket-programming-in-delphi' –

0

Sie können das gleiche mit einem normalen TThread versuchen, wenn Sie Delphi oder Lazarus verwenden.

type 
      TSeparateThread = class(TThread) 
      private 
      protected 
      public 
       constructor Create(IfSuspend: Boolean); 
       proceedure Execute; override; 
      // variables to fill go here 
      // s : String; 
      // i : Integer; 
      // etc... 
      end; 

     constructor TSeparateThread.Create(IfSuspend: Boolean); 
     begin 
      inherited Create(IfSuspend);  
     end; 

     procedure TSeparateThread.Execute; 
     begin 

    // This is where you will do things with those variables and then pass them back. 

     YourMainUnitOrForm.PublicVariableOf := s[i]; 

    // passes position 0 of s to PublicVariableOf in your Main Thread 

     end; 

Aufruf der neue Thread erfolgt wie folgt:

with TSeparateThread.Create(true) do 
    begin 

    // This is where you fill those variables passed to the new Thread 
      s := 'from main program'; 
      i := 0; 
    // etc... 

    Resume; 

    //Will Start the Execution of the New Thread with the variables filled. 

    end; 
Verwandte Themen