Page 1 sur 2

Utiliser un thread pour transmettre un fichier via FTP

Publié : dim. 16/juil./2023 18:44
par hub73
Bonjour à vous.
Recommendez-vous l'utilisation d'un thread pour envoyer un gros fichier vers un site via FTP ? (aujourd'hui bloqage la fenêtre principale : pas de réponse pendant le transfert).
Le thread peut-il mettre à jour la progressbar d'upload placé sur la fenêtre principale ?
J'aimerai que le programme sache lorsque l'upload est terminé. Et le signale à l'ordinateur
Auriez-vous un exemple ? (surtout pour la structure le code).
Merci.
(Ci dessous extrait de mon code actuel sans thread : FTP_Gerer() appelée dans la boucle principale du programme ).

Code : Tout sélectionner


Procedure FTP_ouvrir()
  
  gParametres\FTP = OpenFTP(#PB_Any,gParametres\NomServeurFTP, gParametres\NomUtilisateurFTP, gParametres\MotDePasseFTP, gParametres\PortFTP)
  
  If gParametres\FTP = 0
    MessageRequester ("Erreur","Impossible de se connecter au site pour transfert !")
    ProcedureReturn #False
  Else
    ProcedureReturn #True
  EndIf
  
EndProcedure

Procedure FTP_transferer_fichier()
  
  Protected Choix
  Protected NomFichierSite$
  Protected CheminFichier$
  
  NomFichierSite$ = GetFilePart (gParametres\CheminFichierFTP$)
  CheminFichier$ = gParametres\CheminFichierFTP$
  
  SetGadgetText (Text_fichier_transfere, "...")
  
  If FTP_verifier_fichier_existe(GetFilePart (CheminFichier$)) = #True
    Choix = MessageRequester ("Avertissement", "Le fichier '" + GetFilePart (CheminFichier$) + "' existe déjà sur le serveur du site, souhaitez-vous définitivement le remplacer ?", #PB_MessageRequester_YesNo | #PB_MessageRequester_Warning)
    If Choix = #PB_MessageRequester_No
      MessageRequester ("Info","Transfert annulée.", #PB_MessageRequester_Info)
      ProcedureReturn #False
    EndIf
  EndIf
  
    If FTP_ouvrir() = #True
  
      If IsFTP (gPArametres\FTP) <> 0 
    
        If CheminFichier$ <> ""
          
          If FileSize (CheminFichier$) <> - 1
          
            gParametres\MaxProgress = FileSize(CheminFichier$)
            gParametres\REsultat = SendFTPFile(gParametres\FTP,CheminFichier$,#CHEMIN_SITE + NomFichierSite$,#True)
            gParametres\Uploade = 1
            
          Else
            
            MessageRequester ("Erreur","Le fichier à transférer n'a pas été trouvé !", #PB_MessageRequester_Error)
            
          EndIf
          
        Else
          
          MessageRequester ("Erreur","Vous devez choisir un fichier sonore auparavant !", #PB_MessageRequester_Error)
          
        EndIf
        
      EndIf
      
    EndIf
    
  EndProcedure

 Procedure FTP_gerer()
    
    If IsFTP (gPArametres\FTP) <> 0
    
      If gParametres\Uploade = #True
       If FTPProgress(gParametres\FTP) = #PB_FTP_Finished
          SetGadgetState(ProgressBar_transfert_fichier_site,100)
          Afficher_message ("Fichier transféré.")
          SetGadgetText (Text_fichier_transfere, GetFilePart(gParametres\CheminFichierFTP$) + " (" + Donner_taille_fichier (gParametres\CheminFichierFTP$) + ")")
          gParametres\Uploade = #False
          FTP_fermer()
          FTP_lister_fichiers_site()
        Else
          SetGadgetState(ProgressBar_transfert_fichier_site,FTPProgress(gParametres\FTP))
          
           If FTPProgress(gParametres\FTP) = #PB_FTP_Error  
             Afficher_message ("Erreur lors de la transmission du fichier !")
             MessageRequester ("Erreur", "Erreur lors de la transmission du fichier !", #PB_MessageRequester_Error)
             AbortFTPFile(gPArametres\FTP)
            gParametres\Uploade = #False
            FTP_Fermer()
          EndIf
      
        EndIf
      EndIf
      
    EndIf
    
  EndProcedure


Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : dim. 16/juil./2023 22:42
par cage
Bonsoir,

J'ai pris l'habitude d'utiliser les Threads partout ou c'est utile voire nécessaire pour le bon fonctionnement des applications PB
Une interface qui gèle parce que le traitement d'un processus dure trop longtemps, ça ne fait pas très pro.
Précaution(s) a prendre en considération pour utiliser les Threads, insérer ces lignes de code au tout début de ton code

Code : Tout sélectionner

EnableExplicit ; toutes les variables doivent êtres déclarées

CompilerIf Not #PB_Compiler_Thread
  CompilerError "'Create threadsafe executable' must be checked."
;;CompilerError "L'option Activer la gestion des thread doit etre activée."
CompilerEndIf
Les options sont disponibles dans le menu Compiler/Compileur Options... (Version anglaise)
Voici le standard pour moi des Options du compilateur:
;Compiler Options
;Compiler Options : Executable format: Windows
;Compiler Options : Create threadsafe executable
;Compiler Options : Enable moderm theme support (for Windows X and above)
;Compile/Run : Create temporary executable in the source directory

Voici un squelette de procédure que j'utilise pour mes Threads
C'est ma solution, et ce n'est que ça.
Je penses que d'autres te donneront leurs solutions.
Pour moi, toutes les solutions sont valables a condition d'y trouver son compte.

Code : Tout sélectionner

Declare ma_procedure(ma_variable$)
Declare ma_procedure_thread(value=#False)

Procedure ma_procedure(ma_variable$)
  Static thread
  If IsThread(thread)
    ProcedureReturn thread
  Else
    thread = CreateThread(@ma_procedure_thread(), #True)
    ProcedureReturn thread
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure ma_procedure_thread(value=#False)
  Static isRunning.b
  
  If isRunning
    ProcedureReturn -1
  Else
    isRunning = #True
  EndIf
  
  Protected tes_variables ; déclarer en protected toutes les variables a utiliser dans la proc.
  
  ;
  ;Le code de ta procedure est a mettre ici
  ;
  
  isRunning = #False ; en fin de procédure
  
 ;ProcedureReturn une_valeur ne peut-être utilisé dans un Thread
 
  ; Tu peux utiliser une ou plusieurs variables alpha. ou num. pour indiquer le bon déroulement ou pas de ta proc.
  ; Si tu déclares une variable CODE_RETOUR_THREAD = 255 avant de créer ton Thread
  ; Si ta procédure se termine bien (Ex: fichier bien transmis), alors CODE_RETOUR_THREAD = #True
  ; autrement CODE_RETOUR_THREAD = #False ou toute valeur qui peut être utile pour prendre une décision
  ; Tu peux donc tester réguliérement le code de retour de ton Thread
  
EndProcedure
cage

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : lun. 17/juil./2023 6:08
par hub73
Merci Cage, j'épluche également la documentation pour en savoir un peu plus. Tes conseils et ta structure m'aide bien. Je suis preneur de tous vos conseils, éléments de vigilance, retours d'expérience à avoir à l'utilisation des threads.

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : lun. 17/juil./2023 22:54
par cage
Bonsoir hub73,

Je n'avais pas répondu a une de tes questions:
Le thread peut-il mettre à jour la progressbar d'upload placé sur la fenêtre principale ?
La réponse est oui, que se soit les menus ou les gadgets dont les progressbar

Je viens de mettre un exemple dans le post Utilisation de WaitThread

cage

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : mar. 18/juil./2023 12:53
par microdevweb
Bonjour,

Bien évidement qu'il vaut mieux créer un Thread pour n'importe quel traitement qui prend du temps. Tu peuxmêm faire du multi threading genre producteur consomateur etc...

Avec Pb tu peux modifier les champs d'une fenêtre dans un thread. Attention : Cela n'est pas vrai dans d'autres langages C,C++,C# un il faut utiliser un thread particulier.

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : mar. 18/juil./2023 20:58
par hub73
Merci, je continue à me documenter la dessus et j'explore vos codes.

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : mer. 19/juil./2023 4:43
par hub73
Bonjour.

Une question supplémentaire.

Dans le cas d'un traitement chronophage. Est-il possible de lancer le traitement, donc un thread depuis le bouton par exemple 'lancer le traitement' depuis la fenêtre principale du programme.

Ensuite avoir un retour du genre traitement terminé ou le thread écrit au fur et à mesure son avancement dans la fenêtre principale (un ListIcon qui sert de log).

Est-il possible d'interdire la lancement d'un second thread si le premier n'est pas terminé. Je pensais rendre le bouton 'lancer le traitement inactif' et le réactiver lorsque le thread est terminé.

Merci à vous.

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : mer. 19/juil./2023 8:41
par microdevweb
Voici un petit exemple de multi threading fait à la va vite. Ce code lance trois threads (avec le bouton) la deuxième attend que la première soit finie et la dernière surveille les deux preimères threads.

Code : Tout sélectionner


Global.i TH1,TH2,TH3
Global mutex = CreateMutex()
Global.b ThreadOneIsFinished = #False
Global.b ThreadTwoIsFinished = #False
Enumeration 
  #MAIN_FORM
  #BT
  #LST
EndEnumeration

Procedure Exit()
  CloseWindow(#MAIN_FORM)
  End
EndProcedure

Procedure Th1Loop(*data)
  ; All other threads await of this is finished
  LockMutex(mutex)
  For i = 1 To 100
    AddGadgetItem(#LST,0,"Action thread 1 N: "+Str(i))
    N + 1
    Delay(100)
  Next
  ; Treatment is finished the other threads can be runed
  ThreadOneIsFinished = #True
  UnlockMutex(mutex)
  KillThread(TH1)
EndProcedure

Procedure Th2Loop(*data)
  ; All other threads await of this is finished
  LockMutex(mutex)
  For i = 1 To 100
    AddGadgetItem(#LST,0,"Action thread 2 N: "+Str(i))
    N + 1
    Delay(100)
  Next
  ; Treatment is finished the other threads can be runed
  ThreadTwoIsFinished = #True
  UnlockMutex(mutex)
  KillThread(TH2)
EndProcedure

Procedure Th3Loop(*data)
  Repeat 
    If ThreadOneIsFinished And ThreadTwoIsFinished
      MessageRequester("Info","All thread are finished")
      KillThread(TH3)
    Else
      ; Give time to CPU to breath
      Delay(1)
    EndIf
  ForEver
EndProcedure

Procedure BtClick()
  ; Create threads and run those
  TH1 = CreateThread(@Th1Loop(),0)
  TH2 = CreateThread(@Th2Loop(),0)
  TH3 = CreateThread(@Th3Loop(),0)
EndProcedure

Procedure OpenForm()
  OpenWindow(#MAIN_FORM,0,0,800,600,"Threads demo",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  ListViewGadget(#LST,10,10,400,580)
  ButtonGadget(#BT,510,10,100,30,"Run Thread ")

  ; Binding management
  BindEvent(#PB_Event_CloseWindow,@Exit(),#MAIN_FORM)
  BindGadgetEvent(#BT,@BtClick())
EndProcedure

OpenForm()

Repeat 
  WaitWindowEvent()
ForEver

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : mer. 19/juil./2023 13:48
par hub73
Merci beaucoup pour cet exemple.

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : jeu. 20/juil./2023 13:14
par microdevweb
Voic un petit tuto que j'avais réalisé sur le multi threading.

viewtopic.php?t=17900

Tous les exemples dérivent de ce petit livre.

http://greenteapress.com/semaphores/Lit ... phores.pdf

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : ven. 21/juil./2023 5:56
par hub73
Bonjour. Merci beaucoup, j'ai commencé à adapter mon code avec les threads et grâce à tous ces exemples cela semble bien fonctionner.

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : dim. 23/juil./2023 14:40
par venom
Bonjour,

Autre question sur ce sujet passionnant. Combien de thrrad peuvent être lancé en même temps ? Quel est la limite ?






@++

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : dim. 23/juil./2023 17:33
par cage
Bonjour,

A ma connaissance, il n'y a pas de limites, si ce n'est celle de la mémoire disponible.

A confirmer par des experts de PB.

cage

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : lun. 24/juil./2023 6:58
par microdevweb
Bonjour,

Je pense que les limites vont dépendre de la mémoire vive du CPU ainsi que du nombre de cœurs du CPU. Sous linux real time (si je ne dis pas bêtise) on peut dédier certains cœurs à certains threads.

Attention : il est par contre important dans une boucle d'écoute d'un thread , de poser un delay d'au moins 1 milliseconde (pour laisser le CPU respirer) sans cela le thread demande beaucoup de ressource au CPU. (ceci est valable avec tous les langages)

La bonne pratique est d'ouvrir la gestion de tache de Windows et de regarder les ressources utilisées par le soft.

Ne pas oublier que c'est l'OS qui va gérer les threads.

Re: Utiliser un thread pour transmettre un fichier via FTP

Publié : lun. 24/juil./2023 10:15
par boddhi
Salut Microdeweb,

Puis-je abuser de ton temps et de tes connaissances en matière de threads ?
microdevweb a écrit : mer. 19/juil./2023 8:41 Voici un petit exemple de multi threading fait à la va vite. Ce code lance trois threads (avec le bouton) la deuxième attend que la première soit finie et la dernière surveille les deux preimères threads.
Dans ton exemple fourni, comment intègrerais-tu la gestion, pour chacun des threads, de mise en pause (avec possibilité de reprise) ou d'arrêt partiel et/ou total des procédures threadées ?

Je te remercie d'avance si tu pouvais m'éclairer sur ces points (je bute sur cet écueil depuis plusieurs semaines et ça commence à me gaver grave :mrgreen:)