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 :aie:, 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 :oops:
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 ? :calim2:
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:
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...