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 :

Besoin d'aide pour restructurer mon code autour de l'objet Process [Débutant]


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Par défaut Besoin d'aide pour restructurer mon code autour de l'objet Process
    Bonsoir a tous,
    Je sollicite de moins en moins le forum (grâce vous) mais cette fois-ci je suis a nouveau bloqué sur un problème un peu épineux pour moi.
    J'ai un code qui fonctionne mais qui m’empêche aujourd'hui d'implémenter correctement l'annulation des Process et je souhaite également supprimer les BackGroundWorker car normalement je ne devrais pas en avoir besoin avec des objets Process.
    Mon problème se situe plus au niveau de l’écriture de la structure du code, je ne sais pas comment m'y prendre en évitant de tout casser et compte tenu des différents points bloquant (listés plus bas) que je pourrais rencontrer. Votre suggestions me seront vraiment d'une aide très précieuse.

    Pour commencer voici mon code simplifié au maximum : (j'ai pris l'exemple de 2 processus d'encodage vidéo avec ffmpeg qui correspondent a un encodage en 2 passes).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Private Sub BackGroundWorkerFFMPEG_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs)
            ConvertWithFFmpeg(TSFile)
    End Sub
    Private Sub ConvertWithFFmpeg(InputFilename As String)
    .... ' Ceci est un grand bloc de code ou je prépare les lignes de commandes entre autres.
    Dim FFMPEG_EXE as string = "ffmpeg.exe"
    Dim CommandeLine as string = "Ma ligne de commande1"
    Call ShellExecuteFFMPEG(FFMPEG_EXE, CommandeLine)
    ....
    CommandeLine = "Ma ligne de commande2"
    Call ShellExecuteFFMPEG(FFMPEG_EXE, CommandeLine)
    ....
    End Sub
    La procédure d’exécution des processus :
    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
    Private Sub ShellExecuteFFMPEG(ByVal ExeFile As String, CommandLine As String)
            Dim MonProcess As New Process
            AddHandler MonProcess.OutputDataReceived, AddressOf OutputDataReceived  
            AddHandler MonProcess.ErrorDataReceived, AddressOf ErrorDataReceived  
            AddHandler MonProcess.Exited, AddressOf ProcessExit
            MonProcess.EnableRaisingEvents = True
            MonProcess.StartInfo.FileName = ExeFile
            MonProcess.StartInfo.Arguments = CommandLine
            MonProcess.StartInfo.CreateNoWindow = True  
            MonProcess.StartInfo.UseShellExecute = False  
            MonProcess.StartInfo.RedirectStandardOutput = True
            MonProcess.StartInfo.RedirectStandardInput = True
            MonProcess.StartInfo.RedirectStandardError = True
     
            MonProcess.Start()  
            MonProcess.BeginOutputReadLine()
            MonProcess.BeginErrorReadLine()
     
            MonProcess.WaitForExit()
            MonProcess.Close()
    End Sub
    Private Sub OutputDataReceived(sender As Object, e As System.Diagnostics.DataReceivedEventArgs)
            If e.Data = Nothing Then Exit Sub
            frmProgress1.SetProgress(e.Data.ToString, True, frmProgress.ProcessNames.FFmpeg)
    End Sub
    Private Sub ErrorDataReceived(sender As Object, e As System.Diagnostics.DataReceivedEventArgs)
            If e.Data = Nothing Then Exit Sub
            frmProgress1.SetProgress(e.Data.ToString, True, frmProgress.ProcessNames.FFmpeg)
    End Sub
    Private Sub ProcessExit(sender As Object, e As System.EventArgs)
                My.Computer.Audio.Play(My.Resources.misc229, Microsoft.VisualBasic.AudioPlayMode.Background) ' Son joué a chaque fin de processus
    End Sub
    Les points et problèmes identifiés :
    1- Pour commencer je crois que l'instanciation des objets Process dans la procédure ShellExecuteFFmpeg est une mauvaise idée, car je ne peux pas accéder à cet objet en dehors de la procédure et a fortiori pour annuler depuis mon formulaire d'affichage de la progression a l'aide de MonProcess.kill ou MonProcess.CloseMainWindow.

    Est ce que vous pensez que le mieux serait d'utiliser 2 objets Process ou un seul ? et ou ? (dans le Form.Load par exemple) ? Comment réecrire ShellExecute dans ce cas ?

    2- Mes Processus se lance dans un backgroundWorker, je dois supprimer ce dernier. A priori cela ne devrait pas me poser trop de problème sauf que j'avais fait cela pour libérer le Thread qui exécute l'affichage de la progression (d’après un post de Pol63 (hier) je devrais utiliser l’événement exited, je n'ai pas bien compris comment cet événement pourrait me permettre d’éviter le freeze puisque celui-ci ne s’exécute qu'une fois que le Processus est terminé (si je pouvais avoir une explication la dessus ça serait sympa).
    (Pour information mon formulaire frmProgress1 me sert pour l'affichage de la progression fournie pas les DataReceived. Ce formulaire est instancié depuis le Thread UI et ma méthode SetProgress utilise une invocation pour permettre l'affichage Cross-Threads).

    3- J'utilise WaitForExit car le 2eme Processus (2eme passe) doit attendre le 1er Processus pour pouvoir s'exécuter. Mais si je supprime le BackGroundWorker cela signifie que le thread UI va s'arretter sur la ligne WaitForExit et donc figer l'affichage. Comment obtenir un affichage dans ces conditions ?

    Je suis conscient de ne pas forcement être très clair dans ma demande mais j'aimerais beaucoup avoir votre aide pour éviter de faire des bêtises et si vous pouvez.
    Merci beaucoup.

  2. #2
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    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 204
    Par défaut
    1
    le mieux serait une classe TraitementVideo avec une variable privée as process (non initialisé)
    depuis un form pour démarrer un processus il faudrait faire
    dim t as new TraitementVideo (les paramètres)
    t.start (et encore tu pourrais démarrer le processus sur le sub new)
    comme ca en dehors de la sub tu as ta variable processus
    après ce n'est pas utile pour tout, sender dans les évènements du process c'est le process (par contre pour un .kill c'est utile)

    tu peux donc instancier autant de TraitementVideo que tu veux, à un instance T chacun aura sa variable processus donc pas de mélange

    2
    process.start n'est pas bloquant, le processus démarre
    je ne sais pas si en interne .net démarre un thread qui démarre le processus, mais ce n'est pas spécialement important
    l'évènement exited est levé quand le processus s'arrête
    c'est l'appel à waitforexit qui est bloquant, il suffit de ne plus l'appeler
    au passage sur ta classe TraitementImage tu peux créer des events pour relayer les infos aux forms
    si les events de la classe process sont sur un thread séparé ca irait dans mon hypothèse que .net démarre un thread pour démarrer le processus
    par contre tu peux te débrouiller pour faire comme le bgw, à savoir repasser sur le thread principal momentanément pour mettre à jours l'affichage

    3
    si tu dois démarrer 2 processus l'un à la suite de l'autre, et toujours les 2, c'est à la classe de le gérer (avoir 2 variables as process par exemple)
    sur exited du 1er processus alors tu démarres le 2ème


    concernant l'annulation, si le programme .exe ne prend pas en charge cette annulation, la seule méthode est alors de tuer le processus
    (éventuellement réfléchir pour tuer le processus si l'utilisateur quitte ton appli, sinon les processus restent)
    par contre si les processus ont créé des fichiers et que tu connais les chemins le mieux serait de les deleter

    edit : à priori ffmpeg est en ligne de commande et ne permet aucun dialogue donc pas d'annulation, donc kill si annulation demandée par l'utilisateur
    et à priori tu connais les chemins des fichiers donc tu dois pouvoir les supprimer (ils seront peut etre encore verouillés pendant quelques millisecondes après le kill, donc retenter plusieurs fois sur une seconde ou deux)


    edit 2 :
    piste d'amélioration, j'imagine que ce programme bouffe pas mal de ressources, auquel cas en lancer plusieurs en même temps peut être contre productif, auquel cas tu peux permettre à l'utilisateur d'en définir plusieurs à faire et t'occuper toi même de les enchainer (en instanciant les classes de traitement au fur et à mesure que la précédente se termine)
    piste d'amélioration 2, si c'est un traitement sans trop de paramétrage tu peux aussi juste lui demander un dossier où seront les fichiers à traiter, un dossier où seront les fichiers terminés et faire un service qui s'occupe h24 de voir s'il y a quelque chose à faire ^^ (ca perd certaines fonctionnalités, mais il suffit par contre de glisser des fichiers dans le dossier)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Par défaut
    Merci beaucoup Pol63, je vais étudier ta solution point par point qui semble répondre a ce dont j'ai besoin. Ça va me prendre du temps et j’aurais peut-être besoin de quelques précisons supplémentaires d'ici a ce week-end, je pense.
    Merci beaucoup

  4. #4
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Par défaut
    Bonsoir,
    Merci Pol63 d'avoir relancé ma créativité. J'ai pu sortir une ébauche de la classe avec quelques ajustements personnels. je n'ai pas encore exécuté une seule ligne mais je reflechie encore autour de ce bout de code pour savoir si il peut s'adapter facilement a différents cas possible.
    Donc je n'ai pas associé une classe a un ou deux Process mais carrément a une liste de Process. C'est le fait de devoir enchaîner 2 processus qui m'a poussé a faire ça. Je pense que l'idée n'ai pas mauvaise mais après je n'ai pas le recul suffisant pour savoir si ce n'est pas une erreur de faire comme cela.
    En réalité j'ai aussi une petite idée derrière la tête, ça me permettrait éventuellement d'avoir une meilleur gestion de mes calculs de progression pour plus tard. Il reste encore beaucoup a faire, notamment dans le StopAll qui est un peu brutal pour l'instant.....
    Concernant les ressources c'est pas un soucis, c'est un logiciel qui ne fait que du traitement vidéo avec de l'encodage pure et dure donc c'est normal que ça pompent pas mal.
    J'ai pas encore testé la sortie pour l’affichage par contre, ça va être la surprise.

    Je suis preneur pour toutes critiques éventuelles notamment sur l’enchaînement des process.
    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
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    Public Class VideoParam
        Private _ExeFile As String
        Public Property ExeFile() As String
            Get
                Return _ExeFile
            End Get
            Set(ByVal value As String)
                _ExeFile = value
            End Set
        End Property
        Private _CommandLine As String
        Public Property CommandLine() As String
            Get
                Return _CommandLine
            End Get
            Set(ByVal value As String)
                _CommandLine = value
            End Set
        End Property
        Private _SyncMode As Boolean
        Public Property SyncMode() As Boolean
            Get
                Return _SyncMode
            End Get
            Set(ByVal value As Boolean)
                _SyncMode = value
            End Set
        End Property
    End Class
     
    Public Class clsVideoProcessing
        Private _ProcessId As Integer
        Private _ListOfAsyncProcess As New SortedList(Of Integer, Process)
        Private _listOfSyncProcess As New SortedList(Of Integer, Process)
        Private _Tasks As New SortedList(Of Integer, VideoParam)
        Event ProcessOutPutDataReceived(ByVal Sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs)
        Event ProcessErrorDataReceived(ByVal Sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs)
        Event ProcessExited(ByVal Sender As Object, ByVal e As System.EventArgs)
        Private Sub New(ByVal VideoParam As VideoParam)
            Me.Add(VideoParam)
        End Sub
        Public Sub Add(ByVal VideoParam As VideoParam)
            Dim Process As New Process
            AddHandler Process.OutputDataReceived, AddressOf OutputDataReceived
            AddHandler Process.ErrorDataReceived, AddressOf ErrorDataReceived
            AddHandler Process.Exited, AddressOf Exited
     
            'MonProcess.SynchronizingObject = Me
            Process.EnableRaisingEvents = True
     
            Process.StartInfo.FileName = VideoParam.ExeFile
            Process.StartInfo.Arguments = VideoParam.CommandLine
            'MonProcess.StartInfo.WindowStyle = ProcessWindowStyle.Maximized
            Process.StartInfo.CreateNoWindow = True        ' True
            Process.StartInfo.UseShellExecute = False      ' False
            Process.StartInfo.RedirectStandardOutput = True
            Process.StartInfo.RedirectStandardInput = True
            Process.StartInfo.RedirectStandardError = True
     
            If VideoParam.SyncMode Then
                Me._listOfSyncProcess.Add(Me._ProcessId, Process)
            Else
                Me._ListOfAsyncProcess.Add(Me._ProcessId, Process)
            End If
            Me._Tasks.Add(Me._ProcessId, VideoParam)
            Me._ProcessId += 1
        End Sub
        Public Sub StartAll()
            Dim Process As Process
            If _ListOfAsyncProcess.Count > 0 Then
                For Each kvp As KeyValuePair(Of Integer, Process) In _ListOfAsyncProcess
                    Process = kvp.Value
                    Process.Start()
                    Process.BeginOutputReadLine()
                    Process.BeginErrorReadLine()
                Next
            End If
            If _listOfSyncProcess.Count > 0 Then
                Process = _listOfSyncProcess.Item(0)
                Process.Start()
                Process.BeginOutputReadLine()
                Process.BeginErrorReadLine()
            End If
        End Sub
        Public Sub StopAll()
            Dim Process As Process
            For Each kvp As KeyValuePair(Of Integer, Process) In _ListOfAsyncProcess
                Process = kvp.Value
                Process.Kill()
            Next
            For Each kvp As KeyValuePair(Of Integer, Process) In _listOfSyncProcess
                Process = kvp.Value
                Process.Kill()
            Next
        End Sub
        Public Property Tasks() As SortedList(Of Integer, VideoParam)
            Get
                Return _Tasks
            End Get
            Set(ByVal value As SortedList(Of Integer, VideoParam))
                _Tasks = value
            End Set
        End Property
        Private Sub OutputDataReceived(sender As Object, e As System.Diagnostics.DataReceivedEventArgs)
            RaiseEvent ProcessOutPutDataReceived(sender, e)
        End Sub
        Private Sub ErrorDataReceived(sender As Object, e As System.Diagnostics.DataReceivedEventArgs)
            RaiseEvent ProcessErrorDataReceived(sender, e)
        End Sub
        Private Sub Exited(sender As Object, e As System.EventArgs)
            Dim Process As Process = CType(sender, Diagnostics.Process)
            Dim ProcessId As Integer
            If Me._listOfSyncProcess.ContainsValue(CType(sender, Process)) Then
                ' Process synchrone terminé
                ProcessId = Me._listOfSyncProcess.IndexOfValue(CType(sender, Diagnostics.Process))
                Me._listOfSyncProcess.Remove(ProcessId)
                Me.StartAll()
            ElseIf Me._ListOfAsyncProcess.ContainsValue(CType(sender, Diagnostics.Process)) Then
                ' Process asynchrone terminé
                ProcessId = Me._ListOfAsyncProcess.IndexOfValue(CType(sender, Diagnostics.Process))
                Me._ListOfAsyncProcess.Remove(ProcessId)
            End If
            Me._Tasks.Remove(ProcessId)
            Process.Close()
        End Sub
    End Class

  5. #5
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    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 204
    Par défaut
    ca m'a l'air pas mal

    Citation Envoyé par BasicZX81 Voir le message
    Concernant les ressources c'est pas un soucis, c'est un logiciel qui ne fait que du traitement vidéo avec de l'encodage pure et dure donc c'est normal que ça pompent pas mal.
    je ne dis pas que c'est anormal
    Citation Envoyé par Pol63 Voir le message
    j'imagine que ce programme bouffe pas mal de ressources, auquel cas en lancer plusieurs en même temps peut être contre productif
    je dis juste que dans certains cas il vaut mieux faire les choses à la suite plutot qu'en même temps, là ca doit prendre plus de processeur que de disque donc c'est à tester ...
    sur un disque dur non ssd, faire plusieurs files de copies de fichiers en même temps peut prendre plus de temps que chacune leur tour
    et en plus ca flingue un peu le disque
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  6. #6
    Membre éclairé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Par défaut
    ca m'a l'air pas mal
    Merci
    J'ai pensé a une chose, j’aurais peut-être besoin t’identifier mes process, par exemple dans ma classe videoParam je pourrais rajouter TaskName ou quelque chose dans ce style, puis l'enregistrer quelque part dans ma Classe VideoProcessing au moment du New ou du Add. Ceci afin pouvoir récupérer cet identifiant dans les évents.
    Je voudrais aussi pouvoir donner un accès public pour chaque Process avec un accès a partir de l'identifiant (on ne sais jamais, c'est au cas ou j'aurais besoin d'arrêter un Process Particulié par exemple) mais ça je devrais savoir faire.

    J'ai vu que l'objet Process possède une propriété ProcessId mais je ne sais pas si ça peut me servir et a quel moment ce ProcessId est connu (au moment du start ?).

    Une idée pour mettre ce système d'identifiant en place ?

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

Discussions similaires

  1. [XL-2007] Besoin d'aide pour parfaire mon code enregistrement
    Par capi81 dans le forum Macros et VBA Excel
    Réponses: 11
    Dernier message: 14/08/2014, 16h31
  2. [XL-2007] Besoin d'aide pour améliorer mon code copier-coller
    Par capi81 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 31/07/2014, 16h14
  3. [VB.NET] besoin d'aide pour déchiffrer un code
    Par pcdj dans le forum Windows Forms
    Réponses: 10
    Dernier message: 27/06/2006, 11h32
  4. [VBA-E] Aide pour éxécuter mon code en cliquant sur un bouton dans excel.
    Par pauletta22 dans le forum Macros et VBA Excel
    Réponses: 53
    Dernier message: 29/05/2006, 13h47
  5. Je besoin d'aide pour terminer mon code
    Par Paulinho dans le forum C++
    Réponses: 7
    Dernier message: 06/11/2005, 23h30

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