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 :

Fluidité application : Thread + Webbrowser + Multi-core


Sujet :

Windows Forms

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 39
    Points : 33
    Points
    33
    Par défaut Fluidité application : Thread + Webbrowser + Multi-core
    Bonjour,

    Mon problème concerne la fluidité d'affichage de mon application.

    J'ai une application "Winform" contenant une Form (FormMain) qui est chargée d'instancier et d'afficher simultanément 2 form :
    - "FormFullscreen" (affichée en Fullscreen) contient un Webbrowser affichant une page html composée d'une animation Flash (appelons-la "FlashGourmand" ) relativement gourmande en ressource.
    - "FormBandeau" (avec TopMost=True et Height=200 px) contient un Webbrower affichant une page html composée d'une animation Flash, un peu moins gourmande que l'autre (appelons-la "FlashBandeau").

    Lorsque j'exécute mon application, cela se traduit par un ralentissement, voir un arrêt, de l'animation dans "FlashBandeau" parce que "FlashGourmand" utilise les ressources.

    Précision importante, si j'exécute simultanément 2 fois mon appli, la 1er fois avec "FormFullscreen", la seconde avec "FlashBandeau", l'affichage est ok, et aucun ralentissement remarquée, ma machine est donc assez puissante pour l'application... (pour précision, je n'ai pas nécessairement besoin d'utiliser cette appli sur une machine peu puissante. Il est également envisageable que la machine disposera d'une processeur multi-core.)

    Après moult recherche, j'ai créé des Thread avec STA, Invoke etc. j'ai également utilisé un backgroundworker qui est sensé permettre de ne pas bloquer lors de l'evenement "navigate" ...

    Bref, pour résumé, pour essayer de palier le problème, j'ai essayé plusieurs solutions :

    - Solution 1 : Création de 2 Threads dans la Form de lancement, 1 Thread pour créer et afficher FormFullscreen et 1 Thread pour créer et afficher FormBandeau -> cela n'a rien changé

    - Solution 2 : Solution 1 + ajout d'un backgroundWorker contenant l'instance du navigateur dans chaque Form -> cela n'a rien changé

    - Solution 3 : Solution 2 + masque d'affinité sur le Thread pour lancer un Thread sur le 1er Core et l'autre sur le 2eme Core. -> là je bloque j'y arrive pas , j'ai tenté le coup avec la propriété "ProcessorAffinity" des objets "ProcessThread" mais ca ne change rien...

    Pour la solution 3, j'ai trouvé quelques liens en VB6 que je n'arrive pas à exploiter, j'ai également trouvé quelques infos http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx en C (???), il semblerait qu'il faille utiliser "SetThreadAffinityMask " mais je n'y arrive pas

    Dans un premier temps, j'aimerais avoir confirmation qu'il est possible de répartir sur plusieurs Threads la charge d'affichage (typiquement les animations Flash) et si oui, quelqu'un dispose t'il d'un exemple en VB.NET ?

    Je termine en précisant qu'il n'est pas possible d'optimiser "FlashGourmand" et que la solution de répartir les Thread sur les cores me parait la meilleure, même si malheureusement "FlashGourmand" n'utilisant qu'un seule core, il risque d'y avoir un core utilisé à 100% et un autre sous-exploitée à 5% (comme je l'ai dit FlashBandeau n'est pas très gourmand).

    Ci-dessous, vous trouverez le code pour la solution 2 :

    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
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    Imports System.Threading
    Public Class FormMain
     
     
        Private Sub FormMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
     
            Dim myThread1 As New ThreadForm()
            Dim monThread1 As New Thread(AddressOf myThread1.affiche)
            monThread1.IsBackground = True
            monThread1.SetApartmentState(ApartmentState.STA)
            monThread1.Start()
            monThread1.Priority = ThreadPriority.Highest
     
     
            Dim myThread2 As New ThreadForm()
            Dim monThread2 As New Thread(AddressOf myThread2.defile)
            monThread2.IsBackground = False
            monThread2.SetApartmentState(ApartmentState.STA)
            monThread2.Start()
            monThread2.Priority = ThreadPriority.Highest
     
     
        End Sub
     
     
        Private Delegate Sub FormInvokeHandler()
        Private Delegate Sub FormInvokeHandler2()
     
        Class ThreadForm
            Public monNavigateur As WebBrowser
            Public m_form As FormPerso
     
            Public Sub New()
                m_form = New FormPerso
                m_form.Show()
            End Sub
     
            Public Sub affiche()
                Try
                    If m_form.InvokeRequired Then
                        m_form.Invoke(New FormInvokeHandler(AddressOf m_form.affiche))
                    Else
                        affiche()
                    End If
                Catch ex As Exception
                    MessageBox.Show("affiche " & ex.Message.ToString)
                End Try
            End Sub
     
            Public Sub defile()
                Try
                    If m_form.InvokeRequired Then
                        m_form.Invoke(New FormInvokeHandler2(AddressOf m_form.defileNav))
                    Else
                        defile()
                    End If
                Catch ex As Exception
                    MessageBox.Show("defile " & ex.Message.ToString)
                End Try
            End Sub
        End Class
     
     
        Class FormPerso
            Inherits Form
     
            Public WithEvents m_monNavigateur As WebBrowser
            Public WithEvents BackgroundWorker1 As System.ComponentModel.BackgroundWorker
            Public WithEvents BackgroundWorker2 As System.ComponentModel.BackgroundWorker
     
     
            Public Sub New()
            End Sub
     
            ''' <summary>
            ''' Affiche FlashGourmand
            ''' </summary>
            ''' <remarks></remarks>
            Public Sub affiche()
                Try
                    Me.TopMost = False
                    m_monNavigateur = New WebBrowser
                    Me.Controls.Add(m_monNavigateur)
                    Me.WindowState = FormWindowState.Maximized
     
                    BackgroundWorker1 = New System.ComponentModel.BackgroundWorker
                    BackgroundWorker1.RunWorkerAsync(m_monNavigateur)
                Catch ex As Exception
                    MessageBox.Show("affiche " & ex.Message.ToString)
                End Try
            End Sub
     
            ''' <summary>
            ''' Affichage FlashBandeau
            ''' </summary>
            ''' <remarks></remarks>
            Public Sub defileNav()
                Try
                    Me.Width = My.Computer.Screen.Bounds.Width
                    Me.Left = 0
                    Me.Height = 200
                    Me.Top = My.Computer.Screen.Bounds.Height - Me.Height
                    Me.TopMost = True
                    Application.DoEvents()
     
                    m_monNavigateur = New WebBrowser
                    Me.Controls.Add(m_monNavigateur)
     
                    BackgroundWorker2 = New System.ComponentModel.BackgroundWorker
                    BackgroundWorker2.RunWorkerAsync(m_monNavigateur)
                Catch ex As Exception
                    MessageBox.Show("defileNav " & ex.Message.ToString)
                End Try
            End Sub
     
            Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
                Try
                    If m_monNavigateur.InvokeRequired Then
                        m_monNavigateur.Invoke(New FormInvokeHandler(AddressOf afficheT))
                    Else
                        afficheT()
                    End If
                Catch ex As Exception
                    MessageBox.Show("BackgroundWorker1_DoWork " & ex.Message.ToString)
                End Try
            End Sub
     
            Private Sub BackgroundWorker2_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker2.DoWork
                Try
                    If m_monNavigateur.InvokeRequired Then
                        m_monNavigateur.Invoke(New FormInvokeHandler(AddressOf defileT))
                    Else
                        defileT()
                    End If
     
                Catch ex As Exception
                    MessageBox.Show("BackgroundWorker2_DoWork " & ex.Message.ToString)
                End Try
            End Sub
     
            Public Sub afficheT()
                Try
                    m_monNavigateur.Dock = DockStyle.Fill
                    m_monNavigateur.Visible = True
                    m_monNavigateur.Navigate("C:/flashGourmand.html")
                Catch ex As Exception
                    MessageBox.Show("afficheT " & ex.Message.ToString)
                End Try
            End Sub
     
            Public Sub defileT()
                Try
                    m_monNavigateur.Dock = DockStyle.Fill
                    m_monNavigateur.Visible = True
                    m_monNavigateur.Navigate("C:/flashBandeau.html")
                Catch ex As Exception
                    MessageBox.Show("defileMoi " & ex.Message.ToString)
                End Try
            End Sub
     
     
        End Class
     
     
     
    End Class

    Merci d'avance à tout ceux qui se pencheront sur mon problème...
    --Même si vous ne connaissez pas la réponse merci d'avoir lut mon post--

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    pas lu toute ton histoire mais je viens de faire 2 tests, les 2 prouves que l'ont peut avoir 2 fenetre sur chacune un thread et que les 2 threads sont indépendants

    voilà une des tentatives :
    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
     
    Public Class Form1
     
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim th As New System.Threading.Thread(AddressOf launch)
            th.Start()
     
        End Sub
     
        Private Sub launch()
            System.Windows.Forms.Application.Run(New Form1)
     
        End Sub
     
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            System.Threading.Thread.Sleep(8000)
        End Sub
    End Class
    (l'autre test était avec un thread qui fait un .showdialog)

    après pour définir qu'un thread va sur tel core, je ne suis pas sur que c'est faisable (il est possible de dire à un processus quels cores il a le droit d'utiliser parmis ceux dispo par contre, mais pas utile ici)
    c'est l'os qui décide quel thread mettre sur quel core, par contre sur un processeur multicore, une application avec plusieurs threads sera forcément plus rapide

    après le webbrowser doit repartir sur les dll d'IE, qui dans ton cas doivent repartir sur le plugin flash, en bref, IE n'a ptete qu'un thread pour gérer les 2 webbrowser, et peut etre que flash aussi pour gérer plusieurs animations n'a qu'un thread (certes ca serait dommage, mais on ne sait jamais)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 39
    Points : 33
    Points
    33
    Par défaut
    Tout d'abord merci

    lors je ne saisi pas réellement pourquoi, mais il semblerait que cela fonctionne, en effet lorsque j'ouvre mes 2 Form en suivant ton exemple, le flashBandeau ne rame pas...

    Si l'on regarde les actions effectuées dans le délégué qiu est passé en paramètre du Thread, tu as :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Private Sub launch()
            System.Windows.Forms.Application.Run(New Form1)
    End Sub
    Alors que moi j'ai la méthode "defile()" de la classe "ThreadForm"...

    J'aimerai comprendre le pourquoi du comment, en fait est ce que c'est l'utilisation de "Application.run" qui a corrigé le problème ou est ce que mon problème était d'utilisé l'instance d'un objet (ThreadForm) qui appartenait à ma FormMain en guise de délégué ?
    --Même si vous ne connaissez pas la réponse merci d'avoir lut mon post--

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    je sais pas trop

    mais à mon avis le mieux c'est d'instancier la fenetre dans un thread séparé du thread principal sinon le form doit appartenir au thread principal
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 39
    Points : 33
    Points
    33
    Par défaut
    Bon j'ai correctement réussi à intégrer ce code dans mon appli,

    en fait j'ai eu pas mal de problème car certaines de mes actions sur la Form étaient effectuées durant son instanciation ce qui posé des pb avec le webbrowser (message du style "Objet non casté" ...) bref on mettant tous un max de chose dans l'évenement "Load" de FormBandeau, ca fonctionne...

    Enfin ca fonctionne, un certain temps puis poufff, message d'erreur comme quoi j'ai un problème avec mes pompages de messages windows.

    Le CLR n'a pas pu effectuer de transition du contexte COM 0x1a43c0 au contexte COM 0x1a4530 pendant 60 secondes.
    Le thread qui possède le contexte/cloisonnement de destination est probablement en train d'attendre ou de traiter
    une opération très longue sans pompage des messages Windows. Cette situation a généralement des effets négatifs
    sur les performances et peut parfois entraîner le blocage de l'application ou
    une utilisation ininterrompue de la mémoire. Pour éviter ce problème, tous les threads STA (Single Threaded Apartment) doivent
    utiliser des primitives d'attente de pompage (par exemple CoWaitForMultipleHandles) et pomper de manière régulière
    les messages lors des opérations qui sont longues à s'exécuter.
    Bref, après recherche de cas similaires, plusieurs personnes conseillent d'effectuer des "application.doevents" dans l'opération lourde, j'ai essayé d'en mettre mais ca ne change rien...

    Sais-tu comment je pourrais faire pour
    utiliser des primitives d'attente de pompage (par exemple CoWaitForMultipleHandles)
    ?
    --Même si vous ne connaissez pas la réponse merci d'avoir lut mon post--

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 39
    Points : 33
    Points
    33
    Par défaut
    Je passe cette discussion en résolu car elle m'a permit de résoudre le problème initial...

    Concernant le problème de pompe de message, je vais créé une nouvelle discussion sur le forum en espérant que cela inspire plus de monde

    Merci encore
    --Même si vous ne connaissez pas la réponse merci d'avoir lut mon post--

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

Discussions similaires

  1. multi-threads et multi-core
    Par Pocus dans le forum Langage
    Réponses: 27
    Dernier message: 11/08/2011, 16h01
  2. [BP7] Multi-cpu, multi-core, multi-thread et programme Pascal
    Par Transgarp dans le forum Turbo Pascal
    Réponses: 6
    Dernier message: 07/04/2008, 18h43
  3. Réponses: 5
    Dernier message: 14/04/2007, 14h12
  4. Threads en environnement multi-core
    Par to24320 dans le forum Concurrence et multi-thread
    Réponses: 1
    Dernier message: 06/02/2007, 12h17

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