Bonjour à tous,

Je voudrais vous soumettre un problème auquel je suis confronté depuis une semaine.

Je suis en train de concevoir un programmes qui inclut un module de communication FTP.
J'ai décidé d'utiliser le composant TIdFtp de Indy 10 (que j'ai mis à jour vers la dernière version à partir du site officiel).

Ce composant offre la possibilité de récupérer et parser automatiquement le contenu d'un serveur via la méthode List.
Toutefois, utiliser List dans le thread principal a le principal désavantage de bloquer le processus, ce qui est quelque peu gênant vu que certains de mes serveurs de test peuvent prendre jusqu'à 5 minutes pour répondre à LIST.

C'est pourquoi je voulais mettre l'appel à List dans un thread séparé. Je manque de connaissance concernant les threads (c'est en fait la première fois que j'utilise des threads dans un projet majeur), et de ce fait je ne suis pas sûr que mon implémentation de List dans ce contexte soit appropriée. J'ai également tenté d'utiliser TIdAntiFreese, mais cela ne semble pas fonctionner.

Le problème avec ce thread est que, chaque fois que je démarre le thread à partir de la procédure mère, j'obtiens une Violation d'accès (lecture à l'adresse "00000004").

Ce qui suit est le code principal de mon thread, qui a pour seul but d'effectuer List.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
constructor TFtpListerThread.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  FreeOnTerminate := false;
  Priority := tpNormal;
end;
 
procedure TFtpListerThread.DoAction;
begin
  if (FtpTrafficBox.teststatus = 0) then     // to make sure that the thread does only one execution
    begin
      try
        FtpTrafficForm.FtpModule.List(nil, '', true);     // the most important line of this thread
      except
        FtpTrafficBox.teststatus := 2;     // teststatus evaluated to 2 in case of failure
      end;
      if (FtpTrafficBox.teststatus = 0) then
        FtpTrafficBox.teststatus := 1;     // on success, evaluated to 1
    end;
end;
 
procedure TFtpListerThread.Execute;
begin
  while not Terminated do
    Synchronize(DoAction);
end;
Vu que le composant TIdFtp n'est pas hébergé dans ce thread, j'ai utilisé Synchronize pour éviter les problèmes d'interblocage (ou du moins, c'est supposé l'éviter).
A ce que je sache, il n'y a aucun moyen de retourner facilement une valeur à la sortie du thread, j'ai donc utilisé une réponse par variable globale pour indiquer au processus appelant que List a été effectué. Je suis certain qu'il y a de meilleurs moyens de faire ça ; je suis ouvert à toute suggestion.

La procédure appelante du thread principal est la suivante :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
 
      teststatus := 0;     // Re-initializes the global variable
      FtpListerThread.Resume;     // Starts thread
      while (teststatus = 0) do
        begin
          sleep(10);
          Application.ProcessMessages;     // Keep process messages while it awaits for the end of the thread (not very elegant, I know)
        end;
      FtpListerThread.Suspend;     // Stops the thread when List has finished
      if (teststatus = 2) then
        begin
           // Procedures in case of failure
        end;
Bien que le debuggueur n'ait pas été très clair sur l'origine du crash, je suis pratiquement sûr que cela se produit quand le thread tente d'effectuer List.
De plus lorsque je tente d'éviter l'appel au thread en mettant List dans une structure try-except, cela est effectué sans aucun problème, excepté pour le problème de lag que je souhaitais éviter avec le thread.
De nombreuses personnes ont reporté des problèmes similaires qui ont été corrigés dans une mise à jour de Indy 10 (maj qui concernait une modification d'un Integer vers un Int64 ou qq chose comme ça). Mettre à jour le Indy 10 original inclus dans Delphi n'a pas résolu le problème.

Je pense que tout a été dit. J'espère que vous serez en mesure de me donner un coup de main dans cette histoire.
Si vous avez besoin d'informations complémentaires, ou si vous voulez me taper sur les doigts pour mon code (dégeu ?), n'hésitez surtout pas.

Merci d'avance pour votre aide.

Steph.