Page 1 sur 1

[Linux] Thread SetGadgetState posent problème

Publié : sam. 07/mars/2009 23:08
par Geo Trouvpatou
Salut tout le monde.

J'ai repris ce petit bout de code qui ressemble à celui que je suis en train de faire, mais en beaucoup plus simple.
Le but est que la ligne qui vient d'être ajoutée soit toujours visible.
Sous Windows ce code ne pose pas de problème.

Le voici :

Code : Tout sélectionner

EnableExplicit
Global  progression.l = 0, quit.l = 0, Event.l

Enumeration
  #Window_principale
  #ProgressBarGadget
  #Button_valider
  #Listview_0
EndEnumeration

Procedure monThread(Parametre)

  Repeat
    progression = progression + 1
    If progression <=100

      AddGadgetItem (#Listview_0, progression, Str(progression))
      ;;;;SetGadgetState(#Listview_0, progression-1) ; ---------------------Si on vire ça plus de problème sous Linux
      SetGadgetState(#ProgressBarGadget, progression)
    EndIf
    Delay(250)
  Until quit = 1
  
EndProcedure

Procedure Open_Window_principale()
If OpenWindow(#Window_principale, 0, 0, 440, 260, "Transfert.", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered)

ProgressBarGadget(#ProgressBarGadget,  35, 20, 360,  10, 0, 100)
ButtonGadget(#Button_valider, 160, 40, 100, 24, "Valider")      
ListViewGadget(#Listview_0, 5, 80, 430, 170)

EndIf 
EndProcedure


Open_Window_principale()


Repeat
    Event = WaitWindowEvent()
   
    If Event =  #PB_Event_Gadget
      Select EventGadget()
         
        Case #Button_valider
        CreateThread(@monThread(), 0)  
      EndSelect
    EndIf
   
 Until Event = #PB_Event_CloseWindow

Si on décommente la ligne : SetGadgetState(#Listview_0, progression-1)
on a le droit à des tas de messages de ce type :
[WARNING] g_main_context_prepare(): main loop already active in another thread.
et le programme plante de façon aléatoire.

J'ai essayé d'autres fonctions, mais aucune ne m'a satisfait.

J'ai utilisé Google avec le message d'erreur
http://www.developpez.net/forums/d28796 ... er-thread/
Ou gege2061 dit :
La boucle principale et les threads ne font pas bon ménage, tu doit exécuter gtk_main dans un premier thread et ton code ci-dessus dans un autre thread ?
Je suis allé voir la FAQ GTK : http://gtk.developpez.com/faq/?page=gtk ... CLE_thread
Pourquoi mon programme se bloque lorsque j'utilise les threads ? :
Si vous êtes sûr que votre code est exempt de bug, cela peut-être dû à une mauvaise utilisation des threads. En effet ces derniers ne doivent pas être utilisés en parallèle à la boucle principale du programme (lancée par la fonction gtk_main). Il faut simplement ajouter une fonction à cette boucle.
Bon là c'est déjà hors de mes compétences et j'ai l'impression que c'est la solution :(.

Je me suis risqué sur le forum anglais, malgré que Aie s'pique note véri goud ine angliche et je suis tombé sur ce post :
http://www.purebasic.fr/english/viewtop ... d+function
D'ailleurs au passage c'est le code de Erhk que j'ai pris et que j'ai réduit encore plus.
Et bon, ben j'ai pas trop compris.

Ce qui est bizarre c'est que SetGadgetState ne pose pas de problème avec un ProgressBarGadget???

Avec tous ceux qui bidouillent sous Linux je pense que vous avez déjà dû avoir à faire un SetGadgetState sur un ListViewGadget?

J'espère que vous pourrez m'aider.

Bye.

Publié : dim. 08/mars/2009 13:23
par Anonyme
GTK utilise ses propres "Callback" ou thread pour les événements ,
g_signal_connect_() permet de connecter une action , donc plus de gestion d'événements dans ta boucle principale :

Après , tu n'est pas obligé d'utilisé des threads. mais des drapeau

ex:
if BoutonPressed
MonDrapeau.b = true
endif

if MonDrapeau == true and ProgressBar < 99
MiseAJourDuProgressBar
endif


Code : Tout sélectionner

EnableExplicit
Global  progression.l = 0, quit.l = 0, Event.l

Enumeration
  #Window_principale
  #ProgressBarGadget
  #Button_valider
  #Listview_0
EndEnumeration

Procedure monThread(Parametre)

  Repeat
    progression = progression + 1
    If progression <=100

      AddGadgetItem (#Listview_0, progression, Str(progression))
      SetGadgetState(#Listview_0, progression-1) ; ---------------------Si on vire ça plus de problème sous Linux
      SetGadgetState(#ProgressBarGadget, progression)
    EndIf
    Delay(128)
  Until quit = 1
 
EndProcedure

CompilerIf #PB_Compiler_OS	= #PB_OS_Linux
Procedure Quit()
	gtk_main_quit_()
EndProcedure
CompilerEndIf

Procedure Open_Window_principale()
Protected*Button.i,*Window.i

*Window = OpenWindow(#Window_principale, 0, 0, 440, 260, "Transfert.", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered)

If *Window
ProgressBarGadget(#ProgressBarGadget,  35, 20, 360,  10, 0, 100)
*Button = ButtonGadget(#Button_valider, 160, 40, 100, 24, "Valider")     
ListViewGadget(#Listview_0, 5, 80, 430, 170)


CompilerIf #PB_Compiler_OS	= #PB_OS_Linux
; Connection du "thread" au bouton
g_signal_connect_(*Button,"clicked",@monThread(),*Window)
; Gestion de la sortie
g_signal_connect_(*Window, "destroy", @quit(), #Null)
CompilerEndIf

EndIf
EndProcedure


Open_Window_principale()


Repeat
    Event = WaitWindowEvent()
   
   
   
   CompilerIf #PB_Compiler_OS	= #PB_OS_Windows
   
    If Event =  #PB_Event_Gadget
      Select EventGadget()
         
        Case #Button_valider
        CreateThread(@monThread(), 0) 
      EndSelect
    EndIf
   
   CompilerEndIf
    
   
 Until Event = #PB_Event_CloseWindow

Publié : dim. 08/mars/2009 20:28
par Geo Trouvpatou
Merci à toi Cpl.Bator :D.
Cela fait une heure que je teste, et j'ai dû faire quelques modifs pour que cela fonctionne mieux et surtout que cela fonctionne aussi sous Windows (A vrai dire le code actuel ne fonctionnait pas sous Windows :oops:).

Hélas, il est maintenant un peu tard, je développerais donc un peu mieux demain, pour dire ce que j'ai compris et ce que me dépasse.

Mais en tout cas, c'est vraiment du sport de faire une application totale portable, rien que quand je vois la difficulté pour faire ce que je veux avec ce tout petit bout de code.

A demain ou plus tard pour la suite.

Publié : lun. 30/mars/2009 11:58
par Geo Trouvpatou
Salut.

Bon je remonte ce post pour le dépoussiérer un peu.

Dejà, bonne nouvelle, je disais que c'était du sport de faire une application Dows/Nux, et bien cela a été plus facile que je ne le croyais.
Bon ce n'est pas fini non plus :roll:.
Au départ lors du transfert de mes fichiers, cela Freezait, les progressBar ne se raffraichissaient pas, je ne savais pas interrompre le transfert en cours etc...
Maintenant c'est 100% fonctionnel Windows et 99% fonctionnel sous Linux.

Donc voici un code test qui reflète mieux mon code original.

Code : Tout sélectionner

EnableExplicit
Global Event.i, ThreadID.i, interruption.i

Enumeration
    #Window_principale
    #ProgressBarGadget
    #Button_valider
    #Button_arreter
    #Listview_0
EndEnumeration



Procedure envoiFichier()
    Protected valeurMessageRequester.i, progression.i
    
    Debug "Prog : "+ Str(progression)
    Debug "Interruption : "+ Str(interruption)
    
    Repeat
        
        progression = progression + 1
        If progression <=100
            
            AddGadgetItem (#Listview_0, progression - 1, Str(progression))
            SetGadgetState(#Listview_0, progression - 1)
            
            SetGadgetState(#ProgressBarGadget, progression)
            
            ; Permet d'interrompre le transfert et de proposer si l'on veut arrêter définitivement celui-ci.
            If interruption = 1
                interruption = 0 ; On remet à zéro (évite de s'arrêter à la boucle suivante si on choisit "non"
                
                valeurMessageRequester = MessageRequester("Attention", "Voulez-interrompre le transfert?", #PB_MessageRequester_YesNo)
                If valeurMessageRequester = 6     ; le bouton Oui a été choisi (Resultat = 6)
                    
                    ; -----------------------------------------------------
                    ;              LE PROBLEME EST ICI
                    ; Comment arrêter le processus "monThread" sous Linux
                    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
                        KillThread(ThreadID) ; Pour Windows c'est nickel :)
                    CompilerElse
                        ; Comment arrêter le processus "monThread" sous Linux
                    CompilerEndIf   
                    ; -----------------------------------------------------
                    
                Else ; le bouton Non a été choisi (Resultat = 7) donc on continue le transfert.
                    MessageRequester("C'est ton meilleur choix de la journée.", "Bon on continue alors.", #PB_MessageRequester_Ok)
                EndIf
            EndIf
            
            ;Debug " interruptionINTERNE : "+ Str(interruption) 
        EndIf
        
        Delay(128)
        
    Until progression >=100
    
EndProcedure


Procedure monThread(Parametre)
    
    ; Création d'un dossier
    
    ; Là, on envoi les fichiers dans le dossier qui vient d'être créé
    envoiFichier()
    
    
    ; Création d'un autre dossier
    
    ; Là, on envoi les fichiers dans cet autre dossier
    envoiFichier()
    
    ; etc...
    
EndProcedure



CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    
    Procedure Quit()
        gtk_main_quit_()
    EndProcedure
    
    Procedure stopperTransfert()
        interruption = 1
        ;Debug interruption
    EndProcedure
    
CompilerEndIf

Procedure Open_Window_principale()
    Protected *Button.i, *ButtonArreter.i, *Window.i
    
    *Window = OpenWindow(#Window_principale, 0, 0, 440, 260, "Transfert.", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)
    Debug *Window
    
    If *Window
        ProgressBarGadget(#ProgressBarGadget,  35, 20, 360,  10, 0, 100)
        *Button = ButtonGadget(#Button_valider, 100, 40, 100, 24, "Valider")   
        *ButtonArreter = ButtonGadget(#Button_arreter, 240, 40, 100, 24, "Arreter")   
        ListViewGadget(#Listview_0, 5, 80, 430, 170)
        
        
        CompilerIf #PB_Compiler_OS   = #PB_OS_Linux
            ; Connection du "thread" au bouton
            g_signal_connect_(*Button, "clicked", @monThread(), *Window)
            g_signal_connect_(*ButtonArreter, "clicked", @stopperTransfert(), *Window)
            
            ; Gestion de la sortie
            ;g_signal_connect_(*Window, "destroy", @Quit(), #Null) ; Erreur sur cette ligne
            g_signal_connect_(*Window, "destroy-event", @Quit(), #Null) ;----- Code modifié
            
        CompilerEndIf
        
    EndIf
EndProcedure



Open_Window_principale()



Repeat
    Event = WaitWindowEvent()
    
    CompilerIf #PB_Compiler_OS   = #PB_OS_Windows
        
        If Event =  #PB_Event_Gadget
            Select EventGadget()
                    
                Case #Button_valider
                    ThreadID = CreateThread(@monThread(), 0)
                    
                Case #Button_arreter
                    interruption = 1
                    
            EndSelect
        EndIf
        
    CompilerEndIf
    
Until Event = #PB_Event_CloseWindow
; IDE Options = PureBasic 4.30 (Linux - x86)
; CursorPosition = 92
; FirstLine = 62
Mon petit problème se passe dans la procédure "envoiFichier()"
Si on arrête le transfert des fichiers en plein milieux, sur Windows on fait un "KillThread(ThreadID)", le transfert est arrêté, et apparement tout est ok, rien n'est bloqué (Pas de freeze au niveau de l'interface) et en mode débugguage le transfert est bien arrêté.
Mais comment faire avec Linux???


1) J'ai remplacé :
g_signal_connect_(*Window, "destroy", @Quit(), #Null)
par :
g_signal_connect_(*Window, "destroy-event", @Quit(), #Null)
parce que sinon le compilo me mettait une erreur.
J'imagine que j'ai bien fait?

2) Apparemment pour PB on prend les fonctions GTK et on leur colle un underscore à la fin???
Bon fallait le savoir, c'est marqué quelque part?

3) La signification de :
g_signal_connect_(*Button, "clicked", @monThread(), *Window)
c'est bien :
g_signal_connect_(Sur quel gadget se situe l'action, "Quel type d'évènement sur ce gadget", @Quel procedure on active, *Où se situe le gadget)
Le dernier paramètre je n'en suis pas sûr.

4)
Après , tu n'est pas obligé d'utilisé des threads. mais des drapeau
Dans ma procédure "envoiFichier()" avec :

Code : Tout sélectionner

If interruption = 1
;-- Code
EndIf
Est-ce que c'est cela que tu appelles drapeau?

Parce que pour moi un drapeau c'est un flag et c'est ce qui correspond ci-dessous à la partie rouge :
OpenWindow(#Window_principale, 0, 0, 440, 260, "Transfert.", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered)

5) En regardant la doc pour : OpenWindow() il est écrit :
Resultat = OpenWindow(#Fenetre, x, y, LargeurInterne, HauteurInterne, Titre$ [, Options [, FenetreMereID]])
le numéro de la fenêtre sera renvoyé dans 'Resultat'.
Et plus loin :
Si Resultat = 0, la fenêtre ne peut être ouverte.

Donc Resultat correspond à quoi?
-Un simple nombre d'identification aléatoire?
-L'adresse de cette fenêtre?

6) Quand tu fait :
*Window = OpenWindow(param etc..)
Window est bien une variable de type "pointeur"?
Donc prévue pour stocker une adresse?
Bon je ne peux pas aller plus loin dans mes questions parce que cette question 6 est en rapport avec la 5ème.

7) Dans ma procédure "envoiFichier()", interruption est égale à 1 ou 0, donc j'imagine qu'il serait plus judicieux de mettre booléen pour son type?

8 ) Ai-je bien déclaré mes variables (les Global et Protected)?

Allez, je m'arrête ici pour l'instant avec mes questions.


Bye.

Publié : lun. 30/mars/2009 12:11
par cha0s
après ouverture de la fenêtre essaye

Code : Tout sélectionner

*Window = WindowID(#Window_principale)
pareil pour les gadgets avec gadgetID()

Publié : lun. 30/mars/2009 12:20
par Backup
Parce que pour moi un drapeau c'est un flag et c'est ce qui correspond ci-dessous à la partie rouge :
OpenWindow(#Window_principale, 0, 0, 440, 260, "Transfert.", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered)
ben non :)

un flag c'est une variable, qui sert au programmeur pour savoir qu'un evenement a eu lieu !!

ce que tu cite, ce sont des parametres optionels ! de plus en constante !

un flag , c'est generalement contenu dans une variable !!

d'ailleurs c'est un peu comparable au registre d'etat en assembleur :)
registre qui permet de savoir si il y a une retenue, un depassement de capacité etc !!

souvent reprensenté par une valeur genre "0000000000000000"
(pour un registre de 16 bit )

bref dans ce cas chaque bit correspond a une info precise

voila ce qu'est un flag !!

en basic un flag pourra etre


if toto = 1 ...... si toto=1 cela veut dire que le sprite est sorti de l'ecran :)

c'est un exemple :)

Publié : lun. 30/mars/2009 16:33
par Geo Trouvpatou
Salut.

@cha0s
Je n'ai pas saisit ce que tu voulais me faire comprendre.

@Dobro
Dobro a écrit :un flag c'est une variable, qui sert au programmeur pour savoir qu'un evenement a eu lieu !!
ce que tu cite, ce sont des parametres optionels ! de plus en constante !
un flag , c'est generalement contenu dans une variable !!
Ben pourtant en lisant cet article : http://www.siteduzero.com/tutoriel-3-14 ... faces.html à un moment il est écrit :
Pour ce code :

Code : Tout sélectionner

// Chargement de la vidéo, de l'audio et du timer
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);
Ces "options" que l'on envoie à SDL_Init sont aussi appelées flags. C'est quelque chose que vous rencontrerez assez souvent.
Retenez bien qu'on utilise la barre verticale "|" pour combiner les options. Ca agit un peu comme un opérateur d'addition (d'ailleurs le + peut généralement être utilisé à la place, mais il est préférable d'utiliser le symbole | qui marche dans tous les cas).
Dobro a écrit :voila ce qu'est un flag !!
en basic un flag pourra etre
if toto = 1 ...... si toto=1 cela veut dire que le sprite est sorti de l'ecran Smile
c'est un exemple Smile
Donc dans ma procédure "envoiFichier()" le code:
If interruption = 1
;-- Code
EndIf
Est un drapeau?
Si oui, dans la plupart des langages, on dit plutôt condition.
Les conditions en PHP.

Merci d'avoir répondu, mais hélas, bon nombre de mes questions n'ont pas trouvée de réponse :( .

Bye.

Publié : lun. 30/mars/2009 16:55
par cha0s
si tu avait lue la doc tu aurait comprit que WindowID et GadgetID renvoie le handle a utiliser pour les fonctions des API.

Publié : lun. 30/mars/2009 17:21
par Geo Trouvpatou
Je ne fais que ça de lire la doc, d'ailleurs si tu relis ma question 5, tu verrais que je le RTFM :lol:.
Mais étant débutant en PB ainsi que tout autre langage compilé il y a beaucoup de termes que je ne comprend pas, comme le handle.
Et quand on me dit API, personnellement je pense de suite à Windows.
Parce que l'on parle souvent de l'APIWindows.
cha0s a écrit :si tu avait lue la doc tu aurait comprit que WindowID et GadgetID renvoie le handle a utiliser pour les fonctions des API.
cha0s a écrit :après ouverture de la fenêtre essaye

Code : Tout sélectionner

*Window = WindowID(#Window_principale)
pareil pour les gadgets avec gadgetID()
Tu répondais à laquelle de mes questions, la 5 je suppose?
Si oui ce serais bien de répondre à la 6ème, cela me permettrai d'avancer un peu (ou reculer).

Bye.

Publié : lun. 30/mars/2009 17:41
par cha0s
bon récapitulons les fonctions de l'API sont spécifique au système d'exploitation (même si il est vrai il n'existe pas d'API linux). Elles se finissent par un "_".
gtk_main_quit_() par exemple est spécifique a linux

Or je remarque que tu fait par exemple ceci

Code : Tout sélectionner

g_signal_connect_(*Button, "clicked", @monThread(), *Window)
et je dit mon dieu

OpenWindow() par exemple te retourne si la fonction a réussi sauf si tu utilise #pb_any ou le résultat sera l'identifiant de la fenêtre.

Code : Tout sélectionner

OpenWindow(#Window_principale, 0, 0, 440, 260, "Transfert.", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_SizeGadget)
Ici #Window est l'identifiant de ta fenêtre, c'est donc un handle MAIS c'est celui pour purebasic et si tu fait WindowID(#Window) tu récupère le handle utilisé par ton système d'exploitation pour les commandes lié au système comme l'API.

Par conséquent

Code : Tout sélectionner

g_signal_connect_(*Button, "clicked", @monThread(), *Window)
devient

Code : Tout sélectionner

g_signal_connect_(GadgetID(#Button_valider), "clicked", @monThread(), WindowID(#Window_principale))

Publié : lun. 30/mars/2009 18:21
par Geo Trouvpatou
Bon voici le code rectifié :
Avec du coup les variables *Button.i, *ButtonArreter.i, *Window.i virées.

Code : Tout sélectionner

EnableExplicit 
Global Event.i, ThreadID.i, interruption.i 

Enumeration 
    #Window_principale 
    #ProgressBarGadget 
    #Button_valider 
    #Button_arreter 
    #Listview_0 
EndEnumeration 



Procedure envoiFichier() 
    Protected valeurMessageRequester.i, progression.i 
    
    Debug "Prog : "+ Str(progression) 
    Debug "Interruption : "+ Str(interruption) 
    
    Repeat 
        
        progression = progression + 1 
        If progression <=100 
            
            AddGadgetItem (#Listview_0, progression - 1, Str(progression)) 
            SetGadgetState(#Listview_0, progression - 1) 
            
            SetGadgetState(#ProgressBarGadget, progression) 
            
            ; Permet d'interrompre le transfert et de proposer si l'on veut arrêter définitivement celui-ci. 
            If interruption = 1 
                interruption = 0 ; On remet à zéro (évite de s'arrêter à la boucle suivante si on choisit "non" 
                
                valeurMessageRequester = MessageRequester("Attention", "Voulez-interrompre le transfert?", #PB_MessageRequester_YesNo) 
                If valeurMessageRequester = 6     ; le bouton Oui a été choisi (Resultat = 6) 
                    
                    ; ----------------------------------------------------- 
                    ;              LE PROBLEME EST ICI 
                    ; Comment arrêter le processus "monThread" sous Linux 
                    CompilerIf #PB_Compiler_OS = #PB_OS_Windows 
                        KillThread(ThreadID) ; Pour Windows c'est nickel :) 
                    CompilerElse 
                        ; Comment arrêter le processus "monThread" sous Linux 
                    CompilerEndIf    
                    ; ----------------------------------------------------- 
                    
                Else ; le bouton Non a été choisi (Resultat = 7) donc on continue le transfert. 
                    MessageRequester("C'est ton meilleur choix de la journée.", "Bon on continue alors.", #PB_MessageRequester_Ok) 
                EndIf 
            EndIf 
            
            ;Debug " interruptionINTERNE : "+ Str(interruption) 
        EndIf 
        
        Delay(128) 
        
    Until progression >=100 
    
EndProcedure 


Procedure monThread(Parametre) 
    
    ; Création d'un dossier 
    
    ; Là, on envoi les fichiers dans le dossier qui vient d'être créé 
    envoiFichier() 
    
    
    ; Création d'un autre dossier 
    
    ; Là, on envoi les fichiers dans cet autre dossier 
    envoiFichier() 
    
    ; etc... 
    
EndProcedure 



CompilerIf #PB_Compiler_OS = #PB_OS_Linux 
    
    Procedure Quit() 
        gtk_main_quit_() 
    EndProcedure 
    
    Procedure stopperTransfert() 
        interruption = 1 
        ;Debug interruption 
    EndProcedure 
    
CompilerEndIf 

Procedure Open_Window_principale() 
    
    If OpenWindow(#Window_principale, 0, 0, 440, 260, "Transfert.", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_SizeGadget) 
   
        ProgressBarGadget(#ProgressBarGadget,  35, 20, 360,  10, 0, 100) 
        ButtonGadget(#Button_valider, 100, 40, 100, 24, "Valider")    
        ButtonGadget(#Button_arreter, 240, 40, 100, 24, "Arreter")    
        ListViewGadget(#Listview_0, 5, 80, 430, 170) 
        
        
        CompilerIf #PB_Compiler_OS   = #PB_OS_Linux 
            ; Connection du "thread" au bouton 
            g_signal_connect_(GadgetID(#Button_valider), "clicked", @monThread(), WindowID(#Window_principale)) 
            g_signal_connect_(GadgetID(#Button_arreter), "clicked", @stopperTransfert(), WindowID(#Window_principale)) 
            
            ; Gestion de la sortie 
            g_signal_connect_(WindowID(#Window_principale), "destroy-event", @Quit(), #Null)
            
        CompilerEndIf 
        
    EndIf 
EndProcedure 



Open_Window_principale() 



Repeat 
    Event = WaitWindowEvent() 
    
    CompilerIf #PB_Compiler_OS   = #PB_OS_Windows 
        
        If Event =  #PB_Event_Gadget 
            Select EventGadget() 
                    
                Case #Button_valider 
                    ThreadID = CreateThread(@monThread(), 0) 
                    
                Case #Button_arreter 
                    interruption = 1 
                    
            EndSelect 
        EndIf 
        
    CompilerEndIf 
    
Until Event = #PB_Event_CloseWindow 
; IDE Options = PureBasic 4.30 (Linux - x86) 
; CursorPosition = 92 
; FirstLine = 62
Au passage tu n'aurais pas la solution pour mon problème dans la procedure "envoiFichier()"

Bye.

Publié : mar. 31/mars/2009 0:46
par Geo Trouvpatou
Bon je m'auto-réponds.

J'ai trouvé une solution à mon problème, pour stopper mon transfert de fichier en plein milieu.
Ça m'a l'air propre, puisqu'au final j'ai mon CloseFTP.

Donc je déclare une variable globale "continuerTransfert.b = 1"

Dans ma procédure "monThread(Parametre)", j'ouvre ma connection FTP, j'enveloppe chaque actions à réaliser dans une condition If continuerTransfert = 1 ... EndIf et au final je fais mon CloseFTP.

Et dans ma procédure "envoiFichier()" lors du "MessageRequester", lorsque l'on appuie sur le bouton "Oui je veux interrompre le transfert" on donne la valeur 0 à continuerTransfert et du coup le tour suivant on sort de la boucle et dans la procédure "monThread(Parametre)", on ne rempli plus la condition "If continuerTransfert = 1", donc les actions suivantes ne sont pas exécutées et on va à la fin pour fermer la connexion.

Voici le code en question qui ne fonctionne pas aussi bien que mon vrai programme puisque qu'ici la boucle dans "envoiFichier()" est bloquante, donc pour simuler que l'on pouvait reprendre la main, j'ai ajouté : progression = 100 pour sortir de la boucle :wink:

Code : Tout sélectionner

EnableExplicit 
Global Event.i, ThreadID.i, interruption.i , continuerTransfert.b = 1

Enumeration 
    #Window_principale 
    #ProgressBarGadget 
    #Button_valider 
    #Button_arreter 
    #Listview_0 
EndEnumeration 



Procedure envoiFichier() 
    Protected valeurMessageRequester.i, progression.i 
    
    ;Debug "Prog : "+ Str(progression) 
    ;Debug "Interruption : "+ Str(interruption) 
    
    Repeat 
        
        progression = progression + 1 
        If progression <=100 
            
            AddGadgetItem (#Listview_0, progression - 1, Str(progression)) 
            SetGadgetState(#Listview_0, progression - 1) 
            
            SetGadgetState(#ProgressBarGadget, progression) 
            
            ; Permet d'interrompre le transfert et de proposer si l'on veut arrêter définitivement celui-ci. 
            If interruption = 1 
                interruption = 0 ; On remet à zéro (évite de s'arrêter à la boucle suivante si on choisit "non" 
                
                valeurMessageRequester = MessageRequester("Attention", "Voulez-interrompre le transfert?", #PB_MessageRequester_YesNo) 
                If valeurMessageRequester = 6     ; le bouton Oui a été choisi (Resultat = 6) 
                    
                    ; ----------------------------------------------------- 
                    ;              LE PROBLEME EST... ETAIT ICI 
                    CompilerIf #PB_Compiler_OS = #PB_OS_Windows 
                        KillThread(ThreadID) ; Pour Windows c'est nickel :) 
                    CompilerElse 
                        ; Comment arrêter le processus "monThread" sous Linux 
                        continuerTransfert = 0 ; On stoppe le transfert
                        progression = 100 ; Arnaque
                    CompilerEndIf    
                    ; ----------------------------------------------------- 
                    
                Else ; le bouton Non a été choisi (Resultat = 7) donc on continue le transfert. 
                    MessageRequester("C'est ton meilleur choix de la journée.", "Bon on continue alors.", #PB_MessageRequester_Ok) 
                EndIf 
            EndIf 
            
            ;Debug " interruptionINTERNE : "+ Str(interruption) 
        EndIf 
        
        Delay(128) 
        
    Until progression >=100  
    
EndProcedure 


Procedure monThread(Parametre) 
    
    Debug "OpenFTP lancé"
    
    If continuerTransfert = 1
    ; Création d'un dossier 
    Debug " Création d'un dossier 1"
    EndIf
    
    If continuerTransfert = 1
    ; Là, on envoi les fichiers dans le dossier qui vient d'être créé 
    envoiFichier() 
    Debug "envoiFichier 1"
    EndIf
    
    If continuerTransfert = 1
    ; Création d'un dossier 
    Debug " Création d'un dossier 2"
    EndIf
    
    If continuerTransfert = 1
    ; Là, on envoi les fichiers dans cet autre dossier 
    envoiFichier() 
    Debug "envoiFichier 2"
    EndIf
    
     If continuerTransfert = 1
    ; Création d'un dossier 
    Debug " Création d'un dossier 3"
    EndIf
    
    If continuerTransfert = 1
    ; Là, on envoi les fichiers dans cet autre dossier 
    envoiFichier() 
    Debug "envoiFichier 3"
    EndIf
    
    
    ; etc... 
    
    Debug "CloseFTP fermé"
    
EndProcedure 



CompilerIf #PB_Compiler_OS = #PB_OS_Linux 
    
    Procedure Quit() 
        gtk_main_quit_() 
    EndProcedure 
    
    Procedure stopperTransfert() 
        interruption = 1 
        ;Debug interruption 
    EndProcedure 
    
CompilerEndIf 

Procedure Open_Window_principale() 
    
    If OpenWindow(#Window_principale, 0, 0, 440, 260, "Transfert.", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_SizeGadget) 
   
        ProgressBarGadget(#ProgressBarGadget,  35, 20, 360,  10, 0, 100) 
        ButtonGadget(#Button_valider, 100, 40, 100, 24, "Valider")    
        ButtonGadget(#Button_arreter, 240, 40, 100, 24, "Arreter")    
        ListViewGadget(#Listview_0, 5, 80, 430, 170) 
        
        
        CompilerIf #PB_Compiler_OS   = #PB_OS_Linux 
            ; Connection du "thread" au bouton 
            g_signal_connect_(GadgetID(#Button_valider), "clicked", @monThread(), WindowID(#Window_principale)) 
            g_signal_connect_(GadgetID(#Button_arreter), "clicked", @stopperTransfert(), WindowID(#Window_principale)) 
            
            ; Gestion de la sortie 
            g_signal_connect_(WindowID(#Window_principale), "destroy-event", @Quit(), #Null) 
            
        CompilerEndIf 
        
    EndIf 
EndProcedure 



Open_Window_principale() 



Repeat 
    Event = WaitWindowEvent() 
    
    CompilerIf #PB_Compiler_OS   = #PB_OS_Windows 
        
        If Event =  #PB_Event_Gadget 
            Select EventGadget() 
                    
                Case #Button_valider 
                    ThreadID = CreateThread(@monThread(), 0) 
                    
                Case #Button_arreter 
                    interruption = 1 
                    
            EndSelect 
        EndIf 
        
    CompilerEndIf 
    
Until Event = #PB_Event_CloseWindow