IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Fermer sur un Thread principal une fenêtre ouverte (form) sur un autre thread (Timer)


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Par défaut Fermer sur un Thread principal une fenêtre ouverte (form) sur un autre thread (Timer)
    Bonjour,

    J'ai fait plusieurs essais pour fermer une fenêtre d'information d'attente d'un thread principal qui est lancé au démarrage d'une instance.

    La fenêtre d'information d'attente est ouverte avec l'événement System.Timers.Elapsed.

    J'ai donc utilisé un Timer pour différer l'ouverture du message d'attente au cas ou le serveur est "busy".

    Mais cette fenêtre ne peut plus être fermée avec un simple Form.Close(). La commande est bien parcourue au débogage mais

    celle-ci refuse de se fermer.

    Ok, j'ai lu que le Timer s’exécute sur un autre Thread donc comme c'est "Cloisonné" pas d'issue possible.

    J'ai essayé ensuite d'utiliser la méthode Invoke avec Delegate mais je ne suis pas du tout satisfait du résultat car avec la récursivité du Sub, la fenêtre "mouline" et se ferme enfin quand même au bout de 20 à 30 s : cela fait un peu tâche !

    J'ai de nouveau essayé avec le lancement de la commande Application.Run(New Form). La fenêtre d'attente s'ouvre bien à

    l'aide du Timer. Et Surprise, lorsque je lance la commande Application.Exit() : je reste sur le Thread principal, la fenêtre

    se ferme tout de suite et tout fonctionne bien mais je ne sais pas plus pourquoi et si la méthode est "propre" ?

    Premier code avec la fenêtre qui ne se ferme pas du tout (Je n'ai pas mis de code pour la "form" Proxytest car elle ne

    fait qu'afficher un bandeau et du texte dans un label pour l'attente:
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    Imports System.Timers
    
    Module Routine
    
    Private Temps As Timer
    Private ProxTim as boolean
    
    Public Function IntProx() As Boolean
      Dim adrtest As String = "http://www.example.com"        
      Try
         prox = WebRequest.GetSystemWebProxy()
         AdrProxy = prox.GetProxy(New Uri(adrtest))
         proxyObject = New WebProxy(AdrProxy, True)
         proxyObject.UseDefaultCredentials = True
         request = WebRequest.Create(adrtest)
         request.Timeout = 60000
         request.Proxy = proxyObject
         ProxTim= True
         Temps = New Timer()
         Temps.Interval = 1500
         Temps.Enabled = True
         Temps.Start()
         AddHandler Temps.Elapsed, AddressOf OnTimedEvent
         ReponseReq = CType(request.GetResponse, HttpWebResponse)
         If ReponseReq.StatusCode = HttpStatusCode.OK Then
               Temps.Enabled = False
               Temps.Dispose()
               Return False
         End If
    Catch ex As WebException       
          If CType(ex.Response, HttpWebResponse).StatusCode = HttpStatusCode.ProxyAuthenticationRequired Then
               temps2.Enabled = False : temps2.Dispose()
               Return True                 
           End If
    Finally
          If Not ProxTim Then Proxytest.close()      
    End Try      
    End Function
    
    Public Sub OnTimedEvent(source As Object, e As System.Timers.ElapsedEventArgs)
            If ProxTim Then
                ProxTim =False
    	    Temps.Stop()
                ProxyTest.Show()
                ProxyTest.Refresh()
            End If     
    End Sub
    End Module
    
    Public Class ProxyTest
        ' Il n'y a pas de code utilisateur dans la classe ce n'est que de l'affichage de textes"
    End Class
    Deuxième essai après le premier essai qui ne permet pas la fermeture de la fenêtre d'information ProxyTest en essayant de
    déléguer la fermeture :

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    Imports System.Timers
    
    Module Routine
    
    Private Temps As Timer
    Private ProxTim as boolean
    
    Public Function IntProx() As Boolean
      Dim adrtest As String = "http://www.example.com"        
      Try
         prox = WebRequest.GetSystemWebProxy()
         AdrProxy = prox.GetProxy(New Uri(adrtest))
         proxyObject = New WebProxy(AdrProxy, True)
         proxyObject.UseDefaultCredentials = True
         request = WebRequest.Create(adrtest)
         request.Timeout = 60000
         request.Proxy = proxyObject
         ProxTim= True
         Temps = New Timer()
         Temps.Interval = 1500
         Temps.Enabled = True
         Temps.Start()
         AddHandler Temps.Elapsed, AddressOf OnTimedEvent
         ReponseReq = CType(request.GetResponse, HttpWebResponse)
         If ReponseReq.StatusCode = HttpStatusCode.OK Then
               Temps.Enabled = False
               Temps.Dispose()
               Return False
         End If
    Catch ex As WebException       
          If CType(ex.Response, HttpWebResponse).StatusCode = HttpStatusCode.ProxyAuthenticationRequired Then
               temps2.Enabled = False : temps2.Dispose()
               Return True                 
           End If
    Finally
           If Not ProxTim Then Proxytest.CloseForm()
          
    End Try      
    End Function
    
    Public Sub OnTimedEvent(source As Object, e As System.Timers.ElapsedEventArgs)
            If ProxTim Then
                ProxTim =False
    	    Temps.Stop()
                ProxyTest.Show()
                ProxyTest.Refresh()
            End If     
    End Sub
    End Module
    
    
    Public Class ProxyTest
        Private Delegate Sub Clsfrm() 
        Public Sub CloseForm()
            If Me.InvokeRequired Then
                Me.Invoke(New Clsfrm(AddressOf CloseForm), New Object() {})
            Else
                Me.Close()
            End If
        End Sub
    End Class
    Et enfin, le dernier essai qui semble fonctionner parfaitement ? :

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    Imports System.Timers
    
    Module Routine
    
    Private Temps As Timer
    Private ProxTim as boolean
    
    Public Function IntProx() As Boolean
      Dim adrtestAs String = "http://www.example.com"        
      Try
         prox = WebRequest.GetSystemWebProxy()
         AdrProxy = prox.GetProxy(New Uri(adrtest))
         proxyObject = New WebProxy(AdrProxy, True)
         proxyObject.UseDefaultCredentials = True
         request = WebRequest.Create(adrtest)
         request.Timeout = 60000
         request.Proxy = proxyObject
         ProxTim= True
         Temps = New Timer()
         Temps.Interval = 1500
         Temps.Enabled = True
         Temps.Start()
         AddHandler Temps.Elapsed, AddressOf OnTimedEvent
         ReponseReq = CType(request.GetResponse, HttpWebResponse)
         If ReponseReq.StatusCode = HttpStatusCode.OK Then
               Temps.Enabled = False
               Temps.Dispose()
               Return False
         End If
    Catch ex As WebException       
          If CType(ex.Response, HttpWebResponse).StatusCode = HttpStatusCode.ProxyAuthenticationRequired Then
               temps2.Enabled = False : temps2.Dispose()
               Return True                 
           End If
    Finally     
          If Not ProxTim Then Application.Exit()
          
    End Try      
    End Function
    
    Public Sub OnTimedEvent(source As Object, e As System.Timers.ElapsedEventArgs)
            If ProxTim Then
                ProxTim =False
    	    Temps.Stop()
                Application.Run(New ProxyTest)
            End If     
    End Sub
    End Module
    
    
    Public Class ProxyTest
    End Class
    Désolé pour mon message un peu long avec les trois "codes" mais je voulais mettre les trois variantes pour être le plus clair possible.

    Merci d'avance pour votre aide !

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 202
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 202
    Par défaut
    rien compris
    tu es sur un projet de type windows forms avec un sub main en démarrage ?
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Par défaut
    Bonjour,

    Oui, je lance mon instance avec un Sub Main au démarrage (sans form) et suis sous Windows Form.
    Je dois tester si la connexion du logiciel passe par un proxy pour ouvrir ensuite si nécessaire la fenêtre d'authentification (login et password).

    Je lance donc un thread principal (Module) au démarrage qui appelle une fonction de test pour savoir si il y a un proxy derrière la connexion internet.
    Si le proxy ne nécessité pas d'authentification, je ne veux pas qu'une fenêtre de message d'infos s'ouvre puis se ferme rapidement.
    C'est pourquoi j'ai mis un timer qui se charge d'ouvrir la fenêtre d'info (message d'attente) seulement si la réponse du serveur est lente.

    Comme je l'ai dit , avec le timer pas de Form.Close() possible car la "Form" a été ouverte via l'événement Timer.Elapsed donc à priori sur le thread Timer.
    La méthode Invoke ne fonctionne pas bien.
    Il n'y a que la troisième méthode qui fonctionne bien ?

    Comment faire avec la méthode Invoque + Delegate car ça rame et c'est non satisfaisant.

    J'ai oublié de dire que la fenêtre principal du logiciel s'ouvre après les test au lancement à l"aide de la commande Application.Run(Fenêtre principale)

    Merci pour ton aide

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 202
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 202
    Par défaut
    je pourrais t'expliquer tout ça, mais le plus simple serait que tu démarres sur un splashscreen, à savoir un form qui affiche d'attendre pendant que tu testes la connexion, et après tu passes sur telle ou telle fenetre
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mai 2012
    Messages
    38
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Réunion

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2012
    Messages : 38
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    je pourrais t'expliquer tout ça, mais le plus simple serait que tu démarres sur un splashscreen, à savoir un form qui affiche d'attendre pendant que tu testes la connexion, et après tu passes sur telle ou telle fenetre
    Merci Pol63 de t’intéresser à mon problème.

    J'ai épuré un peu le code dans les 3 cas sur le premier message et mis en caractères gras les trois méthodes citées ( Simple Form.Close de la même fenêtre ouverte à l'aide d'un événement Timer.Elapsed),
    Utilisation d'une méthode Invoke et enfin ouverture par Application.Run(New Form) puis Application.Exit.

    J'ai déjà un Splashcreen qui se ferme automatiquement en fin de chargement de ma procédure principale avec un SplashScreen.Close() dans un événement timer du SplashScreen .

    S'il n'y a pas de Proxy, je n'ai pas besoin de réaliser l'affichage du message d'attente.
    Mon test au démarrage consiste donc à savoir si la connexion passe par un serveur Proxy et si il y a nécessité pour l'utilisateur de s'authentifier sur le Proxy.
    Si il y a un Proxy mais sans authentification nécessaire, Charger systématiquement le message d'attente le fait se fermer tout de suite si la connexion au Proxy est rapide (Ce n'est pas très "propre").
    Je dois absolument tester le Proxy car sinon la lecture des informations sur internet via des "BackgroundWorker" sera refusée par le serveur.

    Donc, je veux n'afficher ce message d'attente qu'au bout de 1 à 1,5 secondes pour le cas ou la connexion au Proxy est lente.
    J'aimerai bien faire fonctionner proprement la deuxième méthode (Invoke) car même si la troisième fonctionne très bien,
    je ne comprends pas le schéma suivant sur la troisième méthode:
    - Dans la procédure principale, si fenêtre de message, on ouvre Application.Run(New Form) (message d'attente) via un événement Timer.elapsed
    - Puis Fermeture de cette fenêtre par Application.exit() mais comment être sur que dans certains cas mon programme ne va pas s'arrêter puisque j'utilise l'instruction Application.Exit.
    L'instruction Application.Exit() ne me permet pas directement de dire qu'il faut fermer le message d'attente (si il y a des surcharges je ne les connais pas)
    - Enfin Mon logiciel se lance Application.Run (Ma fenêtre MDI Principale).
    Le logiciel se fermera complètement avec aussi avec Application.Exit() sachant que le message d'attente s'il a été ouvert aura été fermé au lancement après connexion au Proxy.

  6. #6
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 202
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 202
    Par défaut
    pas mieux compris
    je pense que tu te compliques la vie pour rien
    je vais te donner quelques infos quand même, à voir si tu arrives à corriger ton code avec ...

    on ne ferme pas une fenetre avec application.Exit, mais .close (ou .dispose qui libère la mémoire non managée en plus de close)
    application.Exit doit forcer l'arrêt de tous les threads

    avec le sub main l'appli démarre sur un thread
    l'appli se ferme quand tous les threads sont terminés (y a une option dans le projet aussi qui est fermer l'appli à la fermeture de la fenetre principale, à éviter, mettre toutes les fenetres)
    un thread se termine en fin de sub

    .show sur une fenetre l'affiche mais ne bloque pas l'exécution, aussi un .show dans le sub main fait que l'appli s'arrête et on ne voit la fenêtre qu'une fraction de seconde

    application.run est une instruction bloquante, ca ne passe à la ligne de code après tant que la fenetre est ouverte
    elle est souvent utilisée dans un sub main, ca démarre une pompe à message sur le thread actuel, ce thread est alors le seul autorisé à modifier des controles
    quand la fenetre se ferme ca passe à la ligne d'après, et donc l'appli peut se fermer
    si tu veux rouvrir une autre fenetre il faut alors réutiliser application.run
    il n'est pas possible de faire un autre run en même temps sur le même thread (avant que la fenetre soit fermée)
    il est possible de faire un run après un run sur le même thread
    il est possible de faire un autre run sur un autre thread (ce nouveau thread devient alors le thread principal pour cette fenetre, différent de celui de l'autre fenetre)

    quand on veut modifier un controle (ou fermer une fenetre) depuis un autre thread que celui qui a créé la fenetre, il faut passer par un délégué
    pour ca on utilise la fenetre ou un controle de celle ci pour vérifier qu'on est sur un autre thread si on est pas sûr (.invokerequired), et pour demander l'invoke
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    instanceform.invoke(()=>instanceform.close());
    un truc comme ca devrait marcher
    utiliser invoke sur un controle fait que la méthode que tu veux exécuter sera mise sur la pile, l'exécution attendra donc que plus rien ne s'exécute sur son thread
    aussi si tu es en train de faire un traitement long (ce qui est à éviter vu que le thread de ce form sert aussi au rafraichissement de l'interface) il faudra annuler ce traitement

    quand on démarrre un thread, on peut lui dire IsBackground = true, ce qui fait que quand le thread l'ayant démarré s'arrête, le thread enfant s'arrête aussi


    utiliser des timers dans tout ça n'est pas une bonne idée je pense, parce que le thread d'un timer va devenir lié au form, qui bloque le thread via la pompe à message
    l'asynchronisme, des threads, des .sleep, et ca devrait aller

    mais comme je disais je pense que tu te compliques la vie
    si tu as une fenetre de démarrage qui contient tout le code de ton main et tous les tests à faire alors ca sera plus simple, tu peux fermer cette fenetre quand tu veux, tu peux repartir sur une autre quand c'est bon
    et le contenu de cette fenetre peut changer, si tu vois que tu as besoin d'infos tu peux faire apparaitre des textboxes ou autre (via un usercontrol si nécessaire)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Fermer une fenêtre en cliquant sur un bouton
    Par darkterreur dans le forum jQuery
    Réponses: 6
    Dernier message: 28/06/2012, 14h47
  2. Réponses: 1
    Dernier message: 04/06/2012, 16h10
  3. Réponses: 2
    Dernier message: 06/02/2007, 17h18
  4. Centrer une fenêtre ouverte avec window.open et statusbar
    Par Michaël dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 02/01/2006, 13h07
  5. Erreur sur l'ouverture d'une fenêtre popup
    Par misa dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 25/11/2005, 15h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo