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

Windows Forms Discussion :

Async - Task - je nage, je sombre.


Sujet :

Windows Forms

  1. #1
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut Async - Task - je nage, je sombre.
    Bonjour

    Je souhaite tout mes voeux à toute la communauté !
    que cette année soit remplie de code nous amenant à progresser !

    Dans mon projet de traitement de mes fichiers médias, suites aux dernières modifications, j'ai préféré refaire au propre certaines parties.
    De ce fait j'essai d'apporter quelque chose de plus "fluide" dans les phases qui peuvent être assez longues de traitement.

    une fois que j'ai récupéré mes fichiers "médias", j'ai donc un traitement à effectuer sur chacun d'eux.

    Pour chaque fichier, X extractions via MediaInfo (une information particulière à chaque fois, ce que j'ai regroupé sous le nom de template)

    Je voudrais donc tenter d'optimiser au mieux le temps d'execution de tout ceci, ce qui peut s'avéré long. (déjà car il y a à chaque fois ouverture de fichier)

    pour récupérer les données, j'instancie ma classe MediaInfo (MI)
    puis j'ouvre le fichier,
    Puis je peux faire des "Get" en passant certains paramètres

    exemple classique :

    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Dim MI = New MediaLib.MediaInfo
     If MI.Open(f) Then
    	dim res1 as string = MI.Get(StreamKind.Video, 0, "Format")
    	dim res2 as string = MI.Get(StreamKind.Video, 0, "Width")
    	dim res3 as string = MI.Get(StreamKind.Video, 0, "Height")
     end if
     MI.Close()
    MI = Nothing

    Pour faire un peu plus propre et pour par la suite éviter de saisir à la main (exemple en lisant un XML),J'ai regroupé sous une structure les élements suivant :
    • type
    • NumPiste
    • Champ


    que j'ai nommé template et mis l'ensemble dans un list(of template)

    Etape 1 - Récupération des données sur 1 fichier en asynchrone

    Et donc je voudrais pendant que le fichier est ouvert, pouvoir profiter de faire cette récupération de manière asynchrone.

    Pour ce faire, j'ai lu le très bon article :
    http://www.e-naxos.com/Blog/post/De-la-bonne-utilisation-de-AsyncAwait-en-C.aspx

    Mais je remarque qu'à chaque fois quand l'auteur défini sa méthode en async il a mis un await task.Delay justement pour simuler le temps de traitement.
    Ce dont je n'ai pas besoin de mon côté à simuler.

    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Public Async Function Traitement(template As TmpTemplate) as task(of string)
     
            'Nota : sinon retourner template avec String complété
    		Console.WriteLine("Traitement") 
            'Await Task.Delay(100)
            Dim z = MI.Get(template.Type, template.NumPiste, template.Champ)
     
            Return z
     
    End Function

    Etape 2 - Await Task.WhenAll

    Toujours très bon tuto : http://www.e-naxos.com/Blog/post/Tas...-partie-9.aspx
    dans lequel on évoque le task.WhenAll évoqué dans le tuto pour l'asynchronisme.

    pouvoir traiter si possibles plusieurs fichiers et attendre chaque fin de traitement.

    Code vb.net : 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
    Dim lst As New List(Of TmpTemplate) From {
                New TmpTemplate(StreamKind.General, 0, "UniqueID"),
                 New TmpTemplate(StreamKind.General, 0, "DureeStr3"),
        New TmpTemplate(StreamKind.General, 0, "FileSize"),
        New TmpTemplate(StreamKind.Video, 0, "Format"),
        New TmpTemplate(StreamKind.Video, 0, "Width"),
        New TmpTemplate(StreamKind.Video, 0, "Height"),
        New TmpTemplate(StreamKind.Video, 0, "FrameRate"),
        New TmpTemplate(StreamKind.Audio, 0, "Format"),
        New TmpTemplate(StreamKind.Audio, 0, "FormatInfo")
        }
     
    	Dim MI = New MediaLib.MediaInfo
            If MI.Open(f) Then
    			Dim res As String() = Await Task.WhenAll(lst.Select(Function(x) (a.Traitement(x))))
    		End If
            MI.Close()
            MI = Nothing

    Je n'arrive donc pas à faire cohabiter mon task.WhenAll avec le async également je suppose à cause du await obligatoire dans la fonction de traitement, donc pas de retour de task(Of String) etc, tout est bloqué non compilable.

    il doit donc y avoir quelque chose que je ne comprends pas, qui m'échappe... ou je m'y prends mal dans la logique de la chose. J'ai beau triturer des exemples sur le net, la plupart ont soit un await delay ou une fonction de type asynchrone dejà à l’intérieur comme "GetStringAsync" et donc on mets le await devant (que qui dans ma logique correspond finalement à mon await pour mon appel à traitement et non à l’intérieur de la fonction elle même...)

    Je m'y perds... un peu d'aide ne serait pas de refus.
    Merci.

  2. #2
    Inactif  

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2012
    Messages
    4 903
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2012
    Messages : 4 903
    Points : 10 166
    Points
    10 166
    Billets dans le blog
    36
    Par défaut
    Bonjour,

    Je ne connais pas grand chose au C#, mais il existe une bibliothèque pour faire du MediaInfo en .net

    Je ne suis pas prêt à jurer que cela puisse fonctionner de manière asynchrone, mais tu ne risques pas grand chose à regarder.

    Si le cœur t'en dis, un article (VB.net) par quelqu'un que je connais:

    Je viens de vérifier le lien dans l'article. Il mène toujours à la bonne place. Il y a un lien de téléchargement sur la page au bout du lien qui mène sur la page de l'auteur.

  3. #3
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Bonjour Clément,

    Justement, le wrapper que j'ai en vb.net et basé dessus.

    Je l'ai utilisé depuis un bon moment depuis. Mon but étant de rendre l'ensemble plus asynchrone.
    J'avais déjà fini mon projet sans interface d'interaction utilisateur, avec des choses mis en dur.

    Le but étant maintenant d'amélioré le tout en rendant l'ensemble plus "objet" mieux découpé. C'est quelques chose qui va m'être utile et aussi me permet d'apprendre les choses que je ne voit pas dans mon milieu pro, toujours cantonné à refaire plus ou moins le même genre de code.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Points : 1 511
    Points
    1 511
    Par défaut
    Bonjour,

    Je n'arrive donc pas à faire cohabiter mon task.WhenAll avec le async également je suppose à cause du await obligatoire dans la fonction de traitement, donc pas de retour de task(Of String) etc, tout est bloqué non compilable.
    Je ne comprends pas ce que tu veux dire, tu as des exceptions ? donnes les nous.
    Par contre non le await n'est pas obligatoire dans le sens ou tu peux très bien déclarer une Task et ne jamais l'attendre et donc ne jamais avoir de await. await ne devient obligatoire que si tu déclare la méthode appelante comme async, mais ce n'est qu'une déclaration, enlève le async et tu pourras enlever le await...
    Il faut bien comprendre que WhenAll et ces petites soeurs te retourne une Task. tu peux directement attendre la fin de la tache sans bloquer le thread avec un await devant comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Dim res As String() = Await Task.WhenAll(lst.Select(Function(x) (a.Traitement(x))))
    mais pars exemple si tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Dim task As Task =  Task.WhenAll(lst.Select(Function(x) (a.Traitement(x))))
     
    'ici la tache est deja entrain d'être executée dans un autre thread ....
     
    Dim res As String() = Await task ' ici pour aller plus loin il faudra que la tache soit terminée
    ta tache est lancée avant que tu l'attende, tu pourrais d'ailleurs lancé ainsi plusieurs taches et les attendre les une derrière les autres

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Dim task1 As Task =  Task.WhenAll(lst.Select(Function(x) (a.Traitement1(x))))
    Dim task2 As Task =  Task.WhenAll(lst.Select(Function(x) (a.Traitement2(x))))
    Dim task3 As Task =  Task.WhenAll(lst.Select(Function(x) (a.Traitement3(x))))
     
    'ici les 3 taches sont déjà entrain d'être exécutées ....
     
    Await task1
    Await task2
    Await task2
    Console.writeLine("OK")
    dans ce cas les 3 taches sont exécutées en parallèles et si le plus long des traitement dur 5 secondes alors tu auras OK au bout de 5 secondes. (Pour moi un traitement ici correspond à lst.Select(Function(x) (a.Traitement1(x))) )

    Je sais pas si mon explications te sera utile mais c'est un blocage que j'avais eu a l'époque, il faut réfléchir en tache, et le await n'est pas si magique que ça il ne fait que de te rendre la main le temps de l'exécution de la tache, ainsi l'ordre de déclaration des taches et la place du await sont primordial.
    Pour revenir a mon derniere exemple, si j'avais fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Await Task.WhenAll(lst.Select(Function(x) (a.Traitement1(x)))) 
    Await Task.WhenAll(lst.Select(Function(x) (a.Traitement2(x))))
    Await Task.WhenAll(lst.Select(Function(x) (a.Traitement3(x))))
    Console.writeLine("OK")
    et que chaque traitement dur 5 secondes, alors j'aurais eu OK au bout de 15 secondes....

    Je suis plus c# que VB.net, et j'ai pas le temps de traduire ton code mais si j'ai le temps je regarderais de plus près, mais n'hésite pas à lire et relire toute la série de MÔsieur Dahan sur l'asynchronisme, et fais ses petits exemples dans linqPad, pour ma part ces concepts étant un peu abstrait, des exemples rendent les choses plus concrètes

    Bon courage,
    J@ck

  5. #5
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Points : 1 511
    Points
    1 511
    Par défaut
    OUahhah je viens de voir un problème dans ton code !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    Public Async Function Traitement(template As TmpTemplate) as task(of string)
     
            'Nota : sinon retourner template avec String complété
    		Console.WriteLine("Traitement") 
            'Await Task.Delay(100)
            Dim z = MI.Get(template.Type, template.NumPiste, template.Champ)
     
            Return z 
    End Function
    Tu n'as aucun await dans cette méthode alors que tu la déclare async (je pense pas que ça compile du coup, ou au pire tu devrais avoir un warning).
    Modifie ton code ainsi

    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
     
    Public Function Traitement(template As TmpTemplate) 
     
            'Nota : sinon retourner template avec String complété
    		Console.WriteLine("Traitement") 
            'Await Task.Delay(100)
            Dim z = MI.Get(template.Type, template.NumPiste, template.Champ)
     
            Return z 
    End Function
     
    Public Function TraitementAsync(template As TmpTemplate) As Task
            Return Task.Run(Function()
                                Return Traitement(template)
                            End Function)
    End Function
    Comme dis plus haut j'ai du mal avec les déclarations en VB, donc je ne garantie pas que ca compile, surtout que je ne sais pas de quel type est z dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Dim z = MI.Get(template.Type, template.NumPiste, template.Champ)
     
    Return z
    Donc comme tu peux le voir, maintenant tu a une méthode Traitement synchrone =>Traitement(template As TmpTemplate) qui te retourne un string (suivant le type de z) et une asynchrone => TraitementAsync(template As TmpTemplate) As Task, qui te retourne une Task (peut etre Task(of string) dans ton cas suivant toujours le type de z).

    Par convention on mets toujours (même pour les tests ) Async en suffixe du nom de méthode.

    Désormais tu peux appeler la méthode de façon asynchrone, avant rien ne pouvait être asynchrone dans ton code puisque le traitement ne l'était pas.

    J@ck.

  6. #6
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Bonsoir J@ckHerror,

    Merci de me répondre, j'ai lu en diagonale tes explications, (je tente de tenir un peu debout pour la conférence Nvidia, mais je sens que je vais dormir un peu avant quand même)

    J'ai justement lu les articles et refais les exemple de Olivier (qui ont bien sur marchés) et j'ai voulu les adapter à ce que je voulais faire, sauf comme je le disais il y avait toujours un await ou un méthode asynchrone en dernier.

    M'enfin je fais suivre tes exemples et voir.
    Pour la conversion C# / Vb pas de problème, j'utilise le convertisseur de Telerik et corrige ce qu'il ne converti pas. puis j'ai fais un peu de C#/OpenGL aux premières heures de .Net

    Sinon pour LinqPad, j'ai voulu le mettre à jour au travail dans sa dernière version pour justement faire des tests et eu la mauvaise surprise qu'il réactive mon service windows Update en démarrage différé malgré le fait que nos Windows update soit bloqué par l'active directory. j'ai eu le problème de consommation mémoire qui n'a eu de cesse de grandir sur le svchost (wauserv) et sur mon petit poste du travail, la lenteur devient vite effective. Bref après avoir passé du temps pour résoudre ce problème, j'ai repris "mes tâches" et n'ai pas eu le temps de faire de tests sur LinqPad

    Je vais donc me replonger dans les tests dès que je peux, et surement ce week-end si aucun autre imprévu.

    Nota: Quand j'avais mis "je sombre" dans mon sujet c'étais vraiment la sensation dans laquelle je me trouvais, l'impression d'avoir tout tenté sans voir ce qui cloche (et je n'aime pas ne pas comprendre où j'échoue quand je pense avoir compris)

    A bientôt ! pour des nouvelles.

  7. #7
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Points : 1 511
    Points
    1 511
    Par défaut
    Citation Envoyé par conan76 Voir le message
    sauf comme je le disais il y avait toujours un await ou un méthode asynchrone en dernier.
    Oui en effet pour être asynchrone il faut l'être du début à la fin.
    Si on considère que le début c'est le traitement à réaliser, alors il faut le rendre asynchrone, c'est ce que je te montre dans mon dernier poste.
    En gros en c# (merci )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public string Traitement() //ici pas de notion d'asynchronisme.
    {
           //.....
           //traitement qui prend du temps comme un accès bdd, un accès fichier... etc
           //.....
          return "Fin traitement";
    }
     
    public Task<string> TraitementAsync()
    {
        Task.Run(Traitement());
    }
    Task.Run va créer un nouveau Thread, lancé l'exécution du traitement, et te retourne donc une Task (on peut donc voir une Task comme l'ensemble Thread + traitement).
    A partir de la tu viens de permettre d'appeler en asynchrone un traitement qui avant ne pouvait être que synchrone... c'est donc la première chose à faire si tu veux rendre un traitement asynchrone (le coup du j'appel le méthode synchrone dans un Task.Run(..) marche à tous les coups et semble être ton point de blocage)

    Maintenant pour appeler ce traitement, il faudra forcement que la méthode appelante soit déclarée comme async (c'est utile au compilateur), te permettant ainsi d'utiliser await dans la méthode, et donc "attendre" la fin du traitement tout en rendant la main au thread principal.
    Donc par exemple si on veut appeler le traitement au click d'un bouton et afficher le retour du traitement dans un label, le tout sans bloquer l'interface (donc en asynchrone)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    private async void btTraitement_Click_Async(object sender, EventArgs e)
    {
        var task = TraitementAsync();
        //ici le traitement à déjà débuté.
        string resultTraitement = await task; //le await va rendre la main à l'appelant et donc dans ce cas débloquer l'interface, le fil d'exécution reprendra lorsque le traitement sera fini, et à ce moment resultTraitement  sera affecté.
        this.lbResultTraitement.Text = resultTraitement  ;
    }
    J'ai volontairement séparé les différentes étapes, mais un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    private async void btTraitement_Click_Async(object sender, EventArgs e)
    {
        this.lbResultTraitement.Text = await TraitementAsync();
    }
    est tout à fait identique.

    Je te laisse revenir si tu as des questions.

    Bon code,
    J@ck

  8. #8
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Bonsoir J@ckHerror,

    Mon problème est en effet de Passé d'une méthode "Direct" à une méthode Asynchrone, j'avais tenté avec le Task.Run mais j'ai eu la même erreur que j'ai actuellement en ayant converti ton Code C#

    Et donc d'après le message, je dois mettre un await... du coup je ne comprend pa, voulant le mettre "un cran au dessus" (fonction d'appel à TraitementAsync lors de l'appel.
    Quand je dis que quelque chose m'échappe...

    Code vb.net : 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
     
    Public Class Traite
     
        Public Function TraitementAsync() As Task(Of String)
            Return Task.Run(TraitementDirect) 'Erreur ici sur Task.run
        End Function
     
        Public Function TraitementDirect() As String
     
            For i As Integer = 0 To 1000000000
            Next
     
            Return "Terminé"
     
        End Function
     
    End Class


    Nom : TaskRunError.png
Affichages : 1041
Taille : 11,7 Ko

  9. #9
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Bonjour à tous !

    Je viens de finir quelques tests différents pour tenter de comprendre
    Ci dessous les différentes versions

    Je suis sur une machine virtuelle avec 4 Coeurs, j'ai donc ajuster des boucles pour prendre un certains temps et ajouter également du temps pour le 2ème élement à traiter de manière à ce qu'il soit plus long que le 1er.

    Appels Général (dans un main) :
    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            'Ex.base() 'Version Synchrone
            'Ex.Ass()
            'Ex.Ass2()
            'Ex.Ass3()

    Chaque test utilisera une classe "Separator" pour éclater les données de tests, c'est tout bête, on a une chaine en entrée et je demande d'extraire une partie via une méthode de la classe
    ceci à pour but de représenter mon problème dans mon projet d'extraction des informations sur mon fichier (Vidéo,audio ...)

    Classe :
    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Public Class Separator
        Public Sub Eclate(element As String, partie As Integer, Optional Add As Integer = 0)
     
            Console.WriteLine(element & " Partie {0} : {1}", partie, "Début")
     
            For i As Integer = 0 To 500000000 + Add
            Next
     
            Dim ext = element.Split(";")(partie)
            Console.WriteLine(element & " Partie {0} : {1}", partie, ext)
     
        End Sub
    End Class


    Module Ex pour les différents appels de tests (contient toutes les fonctions)
    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Module Ex
        Dim lst As New List(Of String)

    Dans le module il y a les fonctions suivantes que je décris un peu

    En charge de remplir la liste source et d'attendre une touche (le temps que mes CPU redescendent de la compilation)
    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        Public Sub Load()
            lst.Add("1A;1B")
            lst.Add("2A;2B")
            lst.Add("3A;3B")
            lst.Add("4A;4B")
            Console.ReadKey()
        End Sub


    Test Synchrone (on voit que ça prend un certain temps) tout s’enchaîne dans l'ordre:
    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
     Public Sub base()
            Load()
     
            For Each element In lst
     
                Console.WriteLine("element : {0}", element)
                Dim S As New Separator
                S.Eclate(element, 0)
                S.Eclate(element, 1)
                Console.WriteLine()
            Next
            Console.WriteLine("Fin")
     
        End Sub

    Je me concentre que sur le 1er élément, lors du Test, Fin s'écrit en premier, puis le reste est dans l'ordre (1A,1B) donc B s'execute après A
    Code vb.net : 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
     
    Public Sub Ass()
            Load()
     
            Dim t = Task.Run(Function()
                                 Dim element = lst(0)
                                 Console.WriteLine("element : {0}", element)
     
                                 Dim s As New Separator
                                 s.Eclate(element, 0, 100000000)
                                 s.Eclate(element, 1)
                             End Function)
     
     
            Console.WriteLine("Fin")
     
        End Sub

    Cette fois, j'ai mis sous forme de tache l'appel à la méthode d’éclatement et ajouter une boucle pour prendre l'ensemble de la liste
    dans la console j'ai 4 fois mon console.writeLine issu de chacun des élément, puis Fin, puis le traitement avec cette fois un enchevêtrement de A/B
    Code vb.net : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
      Public Sub Ass2()
            Load()
     
            For Each element In lst
     
                Console.WriteLine("element : {0}", element)
                Dim s As New Separator
                Dim tinterne As New List(Of Task)
                tinterne.Add(Task.Run(Sub() s.Eclate(element, 0, 100000000)))
                tinterne.Add(Task.Run(Sub() s.Eclate(element, 1)))
            Next
            Console.WriteLine("Fin")
     
        End Sub


    Cette fois dans cette version j'ai mis en tache l'ensemble de ma liste (une tâche par élément)
    et séparé l'appel à l'éclatement qui lui même est un regroupement de tâche
    j'ai ajouter des wait/when.all pour voir l'impact de chacun d'eux.
    Ci j'enleve le wait de Ass31, j'ai mon "fin" qui arrive avant (c'est mon seul problème que je voudrais bien résoudre car je veux attendre/savoir que l'ensemble est fini)
    le tout est dans ce cas quasi instantanée

    Puis il faudra que je puisse gérer les retours de données aussi, mais petit à petit, je commence à comprendre.

    Code vb.net : 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
     
     Public Sub Ass3()
            Load()
     
            Dim taches As New List(Of Task)()
     
            For Each El In lst
                Dim element As String = El
     
                taches.Add(Task.Run(Sub()
                                        Ass31(element)
                                    End Sub
                            )
                    )
            Next
     
            Dim t As Task = Task.WhenAll(taches.ToArray())
            t.Wait()
            Console.WriteLine("Fin")
        End Sub
     
        Public Sub Ass31(element)
     
            Console.WriteLine("element : {0}", element)
            Dim s As New Separator
            Dim tinterne As New List(Of Task)
            tinterne.Add(Task.Run(Sub() s.Eclate(element, 0, 100000000)))
            tinterne.Add(Task.Run(Sub() s.Eclate(element, 1)))
     
            Dim tt As Task = Task.WhenAll(tinterne.ToArray())
            tt.Wait()
            Console.WriteLine("Fin Wh {0}", element)
        End Sub

  10. #10
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Points : 1 511
    Points
    1 511
    Par défaut
    Citation Envoyé par conan76 Voir le message
    Bonsoir J@ckHerror,

    Mon problème est en effet de Passé d'une méthode "Direct" à une méthode Asynchrone, j'avais tenté avec le Task.Run mais j'ai eu la même erreur que j'ai actuellement en ayant converti ton Code C#
    Bonjour,

    oui comme je te l'ai dis j'ai un problème avec la syntaxe VB.net. Je viens de me faire un petit prog de test, et j'ai réussi à compiler =>
    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
     
    Public Class Form1
        Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim traitement As Traite
            traitement = New Traite()
            Label1.Text = Await traitement.TraitementAsync()
     
        End Sub
    End Class
     
    Public Class Traite
     
        Public Function TraitementAsync() As Task(Of String)
            Return Task.Run(Of String)(Function()
                                           Return TraitementDirect() 
                                       End Function)
        End Function
     
        Public Function TraitementDirect() As String
     
            For i As Integer = 0 To 1000000000
            Next
     
            Return "Terminé"
     
        End Function
     
    End Class
    J'ai juste créé un nouveau projet application vb, j'ai mis un label (Label1) et un bouton (Button1), et donc je clique sur le bouton et je peux alors redimmensionner la form avant d'avoir Terminé dans le label, si je remplace l'appel à la méthode asynchrone par celle synchrone alors je ne peux pas...

    donc pour le task.Run il faut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     Public Function TraitementAsync() As Task(Of String)
            Return Task.Run(Of String)(Function()
                                                      Return TraitementDirect() 
                                                 End Function)
    End Function
    Pas compris pourquoi il faut remettre Function() End Function... si un spécialiste de VB pouvait nous expliquer

    Bref tu y étais, nous avions juste un problème de déclaration VB.

    Bon courage, moi je passe à ton dernier post
    J@ck.

  11. #11
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 742
    Points
    9 742
    Billets dans le blog
    3
    Par défaut
    Je ne suis pas specialiste VB.NET (j'en ai fait quand j'ai commence le .NET en 2003/2004 - donc n'hesitez pas a me corriger si j'ecris des betises ). C'est le moyen d'ecrire une expression lambda en VB.NET. Mettre Function() ... End Function en parametre de la methode Task.Run() revient a ecrire en C# :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Task.Run(() => 
    {
        // Code ici
        var obj = maMethode());
        return obj;
    });
    Dans ce cas, Function() ... End Function est une Func(Of TResult), c'est-a-dire un delegate qui retourne une valeur. Il existe aussi Func(Of T, TResult) qui permet de passer des parametres au delegate, et de retourner un resultat.

    C'est juste du sucre syntaxique pour eviter de devoir ecrire un delegate a chaque fois, et ca offre la possibilite de le faire en "inline", c'est-a-dire de mettre un peu de logique directement au sein de l'expression lambda.

    A verifier, mais je pense qu'on doit aussi pouvoir ecrire Sub() ... End Sub en parametre de Task.Run(), ce qui revient a utiliser Action(Of T), c'est a dire un delegate qui ne retourne pas de valeur et ne prend pas de parametre.

  12. #12
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2005
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2005
    Messages : 562
    Points : 1 511
    Points
    1 511
    Par défaut
    Merci @DotNetMatt pour tes précisions. C'est un peu plus claire.

    Donc pour le cas conan76 c'est bien Function() ... End Function puisqu'on veut un string en retour.

    @conan76 tu dis
    Ci j'enleve le wait de Ass31, j'ai mon "fin" qui arrive avant (c'est mon seul problème que je voudrais bien résoudre car je veux attendre/savoir que l'ensemble est fini)
    Déjà le lien qui va bien

    Tu travaille dans une console, l'exécution est donc forcément séquentielle, et tu ne peux pas faire de await dans le main (cf le lien), tu devras donc forcément "bloquer" à un moment ton main pendant l'exécution d'un traitement long. Le Wait te permet jsutement de faire ça (cf le lien) c'est même uniquement à cela qu'il sert.
    Donc ton code est pas mal (enfin il fait ce que tu veux niveau clarté ), tu réalises en "parallèle" tes différentes taches, et tu sais quand c'est fini.

    Mais pour vraiment comprendre l'asynchronisme et la mettre en pratique (dans ton code tu n'as pas de await tu n'attends donc jamais véritablement au sens asynchrone) je te conseillerais de passer sur une application avec interface, surtout si au final c'est ce que tu auras.

    J@ck.

  13. #13
    Membre du Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2006
    Messages
    128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 128
    Points : 61
    Points
    61
    Par défaut
    Bonjour,

    Désolé de ne pas donner de nouvelles réponses suite à mes tests J@ckHerror, je ne pensais pas avoir un soucis hardware aussi complexe, actuellement sans trouver la/les causes.

    J'avais fais test test qui était ok, mais des que j'étoffé c'étais non concluant. j'avais prévu de séparé les différentes étapes pour illustré le problème mais ce problème hardware et arrivé et me prend tout mon temps perso.

    explications

    J'espère pouvoir un de ces quatre pouvoir reprendre...

Discussions similaires

  1. Appel Api en ajax + async task
    Par Ornitho76 dans le forum ASP.NET MVC
    Réponses: 1
    Dernier message: 17/06/2015, 09h38
  2. Empecher le lancement de plusieurs async task
    Par Sofute dans le forum Android
    Réponses: 4
    Dernier message: 13/01/2014, 13h47
  3. WP 7 et 8 : utiliser les mots clefs await/async et Task<T>
    Par rolandl dans le forum Windows Phone
    Réponses: 2
    Dernier message: 27/03/2013, 09h40

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