2010-11-23 10 views
2

Donc, mon but est de démarrer une fonction dans un autre thread. Aussi j'ai besoin d'accéder à d'autres composants vcl à partir du nouveau thread. Voici mon code à ce jour:Accès au composant vcl dans le fil! 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'; 

mon programme se bloque et j'obtiens l'erreur: Exception EAccessViolation dans le module my.exe à 00154E53. Violation d'accès à l'adresse 00554E53 dans le module 'my.exe'. Lu de l'adresse 00000398.

Merci d'avance.

Répondre

9

La cause de la violation d'accès est que vous transmettez l'adresse d'une méthode TForm à une fonction qui attend un TThreadFunc (voir la documentation of System.BeginThread()). Utiliser Addr() comme ceci est un bon moyen d'empêcher le compilateur de signaler vos bogues. Ce que vous devez faire à la place est d'écrire une fonction wrapper qui a la bonne signature, passer l'instance de formulaire en tant que paramètre, et appeler la méthode sur le formulaire à partir de cette fonction.

Mais ne vont pas là, soit écrire votre code en tant que descendant de TThread, ou (de préférence) utiliser une enveloppe de niveau supérieur comme AsyncCalls ou Omni Thread Library. Et assurez-vous que vous n'accédez pas aux composants VCL dans le thread principal, créez et libérez ceux dont vous avez besoin dans votre thread de travail.

5

La VCL (composants Gui) n'est accessible qu'à partir du thread principal. Les autres threads ont besoin du thread principal pour accéder à la VCL.

+1

et la manière facile d'y arriver est les threads secondaires affichant des messages WM_USER et le thread principal y répondre. Dans votre cas, cependant, vous pouvez obtenir le même effet en utilisant l'objet indy TidAntiFreeze. Lisez ceci 'http: // stackoverflow.com/questions/37185/quoi-le-idiomatique-manière-de-faire-async-socket-programming-in-delphi' –

0

Vous pouvez essayer la même chose avec un TThread standard si vous utilisez Delphi ou Lazarus.

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; 

L'appel du fil se fait comme suit:

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; 
Questions connexes