OVH Cloud OVH Cloud

Pourquoi le marshaling

2 réponses
Avatar
Phil
Voici mon problème. En travaillant sur le multithreading, je suis arrivé à me
préoccuper du marshaling à cause d'un exemple de gestion multithreads
récupéré sur le site Microsotf.FR
(http://msdn.microsoft.com/library/fre/default.asp?url=/library/FRE/vbcon/html/vbconwalkthroughsimplemultithreadedcomponent.asp).
C'est en effet à la fin de l'exemple Calculator sur le multithreading, qu'il
est question d'appels marshaling à des contrôles.
L'exemple que j'ai réécrit ci dessous n'est qu'une version francisée et un
peu simplifiée de l'exemple de Microsoft.

Ce que je comprends de la technique, c'est que le marshaling doit être
implémenté lorsqu'un thread secondaire
active une méthode d'un thread principal. Je comprends aussi que la mise en
œuvre de ce marshaling consiste
simplement à déléguer à une méthode asynchrone, la réaction souhaitée en
réponse à l'action du thread secondaire.

Dans cette logique, l'exemple suivant illustre le marshaling. Il comporte
une classe MesProcedures qui implémente
2 méthodes Traitement1 et Traitement2. Chacun de ces traitements remplit un
vecteur de 11 entiers et génére un
événement ResultatComplet qui est pris en charge dans le module appellant
par la procédure événementielle
ResultatDisponible. Le marshaling consiste à faire exécuter le travail de
cette procédure par une méthode déléguée asynchrone.
J'ai donc déclaré un délégué et je remplace l'appel synchrone de la
procédure d'affichage par son appel asynchrone via le délégué.

Voici le code de la classe.

Imports System.Threading

Public Class MesProcedures

Public Event ResultatComplet(ByRef T() As Integer, ByVal Taille As Integer)

Dim TLocal() As Integer
Dim TailleLocale As Integer

Public Sub New(ByVal Taille As Integer)
ReDim TLocal(Taille)
TailleLocale = Taille
End Sub

Public Sub UneProc1()
SyncLock TLocal ' Verrouillage de TLocal
For i As Integer = 0 To TailleLocale
Thread.Sleep(100)
TLocal(i) = i
Next i
RaiseEvent ResultatComplet(TLocal, TailleLocale)
End SyncLock ' Libèration (après expédition du résultat)
End Sub

Public Sub UneProc2()
SyncLock TLocal ' Verrouillage de TLocal
For i As Integer = 0 To TailleLocale
Thread.Sleep(200)
TLocal(i) = 100 + i
Next i
RaiseEvent ResultatComplet(TLocal, TailleLocale)
End SyncLock ' Libèration (après expédition du résultat)
End Sub
End Class



Voici le code principal qui implémente le marshaling tel que je le comprends.

Public Module MonModule

Public Delegate Sub ResultatPresent(ByRef T() As Integer, ByVal L As
Integer)

Dim TraitementResultat As New ResultatPresent(AddressOf
TraiteResultatDisponible)

Private Sub TraiteResultatDisponible(ByRef T() As Integer, ByVal Longueur
As Integer)
For i As Integer = 0 To Longueur
Console.Write(T(i).ToString("000") & " ") ' Affichage proprement dit
Next
End Sub

Private Sub ResultatDisponible(ByRef T() As Integer, ByVal Longueur As
Integer)
' TraiteResultatDisponible(T, Longueur) ' Pour test avec appel synchrone
TraitementResultat.BeginInvoke(T, Longueur, Nothing, Nothing) 'Appel
asynchrone
End Sub

Public Sub Main()
Dim Procedure As New MesProcedures(10)
Dim Traitement1 As New Thread(AddressOf Procedure.UneProc1)
Dim Traitement2 As New Thread(AddressOf Procedure.UneProc2)
AddHandler Procedure.ResultatComplet, AddressOf ResultatDisponible
Traitement1.Start() ' Doit fournir les valeurs de 0 à 10
Traitement2.Start() ' Doit fournir les valeurs de 100 à 110
Console.ReadLine() ' Attendre la fin des affichages
End Sub
End Module

Bien sûr, jusque là, il n'y a aucun problème et tout fonctionne.
Il y a événtuellement problème si je me suis complètement fourvoyé dans ma
compréhension du marshaling.
Dans ce cas, il serait utile qu'on me dise où j'ai dérapé …

Par contre, il y a réellement problème si ma compréhension et la mise en
œuvre du marshaling sont correctes.
Car dans ce cas, je ne comprends pas pourquoi Microsoft indique ce
dispositif comme étant nécessaire alors
que cela fonctionne encore mieux en multithreading sans marshaling !!!

Après avoir programmé l'exemple MicroSoft, avec et sans marshaling, j'y ai
placé des points de mesures
(Now.TimeOfDay.ToString) de sorte à évaluer les performances. J'ai aussi
effectué les tests en chargeant
les procédures déléguées de traitements supplémentaires (boucle de 1000000
itérations).

Dans tous les cas (déjà même dans l'exemple MesProcedures ci-dessus), le
marshaling provoque une perte de temps.

Alors, voici la question finale : A quoi bon le marshaling quand on fait du
multithreading ?

2 réponses

Avatar
Patrice
A mon avis c'est inutile dans ton code. Note que l'article précise bien
"Appels marshaling à des *contrôles*", le problème étant qu'un contrôle ne
peut-être manipulé que par le thread qui l'a créé...

Donc le Invoke et utile ou non en fonction de ce que fait le code que tu
appelles...

En 2.0, le composant BackgroundWorker peut-être utile...

--
Patrice

"Phil" a écrit dans le message de news:

Voici mon problème. En travaillant sur le multithreading, je suis arrivé à
me
préoccuper du marshaling à cause d'un exemple de gestion multithreads
récupéré sur le site Microsotf.FR
(http://msdn.microsoft.com/library/fre/default.asp?url=/library/FRE/vbcon/html/vbconwalkthroughsimplemultithreadedcomponent.asp).
C'est en effet à la fin de l'exemple Calculator sur le multithreading,
qu'il
est question d'appels marshaling à des contrôles.
L'exemple que j'ai réécrit ci dessous n'est qu'une version francisée et un
peu simplifiée de l'exemple de Microsoft.

Ce que je comprends de la technique, c'est que le marshaling doit être
implémenté lorsqu'un thread secondaire
active une méthode d'un thread principal. Je comprends aussi que la mise
en
ouvre de ce marshaling consiste
simplement à déléguer à une méthode asynchrone, la réaction souhaitée en
réponse à l'action du thread secondaire.

Dans cette logique, l'exemple suivant illustre le marshaling. Il comporte
une classe MesProcedures qui implémente
2 méthodes Traitement1 et Traitement2. Chacun de ces traitements remplit
un
vecteur de 11 entiers et génére un
événement ResultatComplet qui est pris en charge dans le module appellant
par la procédure événementielle
ResultatDisponible. Le marshaling consiste à faire exécuter le travail de
cette procédure par une méthode déléguée asynchrone.
J'ai donc déclaré un délégué et je remplace l'appel synchrone de la
procédure d'affichage par son appel asynchrone via le délégué.

Voici le code de la classe.

Imports System.Threading

Public Class MesProcedures

Public Event ResultatComplet(ByRef T() As Integer, ByVal Taille As
Integer)

Dim TLocal() As Integer
Dim TailleLocale As Integer

Public Sub New(ByVal Taille As Integer)
ReDim TLocal(Taille)
TailleLocale = Taille
End Sub

Public Sub UneProc1()
SyncLock TLocal ' Verrouillage de TLocal
For i As Integer = 0 To TailleLocale
Thread.Sleep(100)
TLocal(i) = i
Next i
RaiseEvent ResultatComplet(TLocal, TailleLocale)
End SyncLock ' Libèration (après expédition du résultat)
End Sub

Public Sub UneProc2()
SyncLock TLocal ' Verrouillage de TLocal
For i As Integer = 0 To TailleLocale
Thread.Sleep(200)
TLocal(i) = 100 + i
Next i
RaiseEvent ResultatComplet(TLocal, TailleLocale)
End SyncLock ' Libèration (après expédition du résultat)
End Sub
End Class



Voici le code principal qui implémente le marshaling tel que je le
comprends.

Public Module MonModule

Public Delegate Sub ResultatPresent(ByRef T() As Integer, ByVal L As
Integer)

Dim TraitementResultat As New ResultatPresent(AddressOf
TraiteResultatDisponible)

Private Sub TraiteResultatDisponible(ByRef T() As Integer, ByVal Longueur
As Integer)
For i As Integer = 0 To Longueur
Console.Write(T(i).ToString("000") & " ") ' Affichage proprement dit
Next
End Sub

Private Sub ResultatDisponible(ByRef T() As Integer, ByVal Longueur As
Integer)
' TraiteResultatDisponible(T, Longueur) ' Pour test avec appel
synchrone
TraitementResultat.BeginInvoke(T, Longueur, Nothing, Nothing) 'Appel
asynchrone
End Sub

Public Sub Main()
Dim Procedure As New MesProcedures(10)
Dim Traitement1 As New Thread(AddressOf Procedure.UneProc1)
Dim Traitement2 As New Thread(AddressOf Procedure.UneProc2)
AddHandler Procedure.ResultatComplet, AddressOf ResultatDisponible
Traitement1.Start() ' Doit fournir les valeurs de 0 à 10
Traitement2.Start() ' Doit fournir les valeurs de 100 à 110
Console.ReadLine() ' Attendre la fin des affichages
End Sub
End Module

Bien sûr, jusque là, il n'y a aucun problème et tout fonctionne.
Il y a événtuellement problème si je me suis complètement fourvoyé dans ma
compréhension du marshaling.
Dans ce cas, il serait utile qu'on me dise où j'ai dérapé .

Par contre, il y a réellement problème si ma compréhension et la mise en
ouvre du marshaling sont correctes.
Car dans ce cas, je ne comprends pas pourquoi Microsoft indique ce
dispositif comme étant nécessaire alors
que cela fonctionne encore mieux en multithreading sans marshaling !!!

Après avoir programmé l'exemple MicroSoft, avec et sans marshaling, j'y ai
placé des points de mesures
(Now.TimeOfDay.ToString) de sorte à évaluer les performances. J'ai aussi
effectué les tests en chargeant
les procédures déléguées de traitements supplémentaires (boucle de 1000000
itérations).

Dans tous les cas (déjà même dans l'exemple MesProcedures ci-dessus), le
marshaling provoque une perte de temps.

Alors, voici la question finale : A quoi bon le marshaling quand on fait
du
multithreading ?





Avatar
Phil
Merci Patrice.

J'avais bien capté la nuance "Cotrôle". Aussi ai-je réalisé ensuite les
tests avec un "Component" conformément à l'article et les résultats n'étaient
pas meilleurs.

En tous cas, tu me confortes dans l'idée que le marshaling n'est pas
nécessaire dans ces exmples.

Je ne connais pas encore le BackgroundWorker. Je vais étudier ça.

Phil

()




"Phil" a écrit :

Voici mon problème. En travaillant sur le multithreading, je suis arrivé à me
préoccuper du marshaling à cause d'un exemple de gestion multithreads
récupéré sur le site Microsotf.FR
(http://msdn.microsoft.com/library/fre/default.asp?url=/library/FRE/vbcon/html/vbconwalkthroughsimplemultithreadedcomponent.asp).
C'est en effet à la fin de l'exemple Calculator sur le multithreading, qu'il
est question d'appels marshaling à des contrôles.
L'exemple que j'ai réécrit ci dessous n'est qu'une version francisée et un
peu simplifiée de l'exemple de Microsoft.

Ce que je comprends de la technique, c'est que le marshaling doit être
implémenté lorsqu'un thread secondaire
active une méthode d'un thread principal. Je comprends aussi que la mise en
œuvre de ce marshaling consiste
simplement à déléguer à une méthode asynchrone, la réaction souhaitée en
réponse à l'action du thread secondaire.

Dans cette logique, l'exemple suivant illustre le marshaling. Il comporte
une classe MesProcedures qui implémente
2 méthodes Traitement1 et Traitement2. Chacun de ces traitements remplit un
vecteur de 11 entiers et génére un
événement ResultatComplet qui est pris en charge dans le module appellant
par la procédure événementielle
ResultatDisponible. Le marshaling consiste à faire exécuter le travail de
cette procédure par une méthode déléguée asynchrone.
J'ai donc déclaré un délégué et je remplace l'appel synchrone de la
procédure d'affichage par son appel asynchrone via le délégué.

Voici le code de la classe.

Imports System.Threading

Public Class MesProcedures

Public Event ResultatComplet(ByRef T() As Integer, ByVal Taille As Integer)

Dim TLocal() As Integer
Dim TailleLocale As Integer

Public Sub New(ByVal Taille As Integer)
ReDim TLocal(Taille)
TailleLocale = Taille
End Sub

Public Sub UneProc1()
SyncLock TLocal ' Verrouillage de TLocal
For i As Integer = 0 To TailleLocale
Thread.Sleep(100)
TLocal(i) = i
Next i
RaiseEvent ResultatComplet(TLocal, TailleLocale)
End SyncLock ' Libèration (après expédition du résultat)
End Sub

Public Sub UneProc2()
SyncLock TLocal ' Verrouillage de TLocal
For i As Integer = 0 To TailleLocale
Thread.Sleep(200)
TLocal(i) = 100 + i
Next i
RaiseEvent ResultatComplet(TLocal, TailleLocale)
End SyncLock ' Libèration (après expédition du résultat)
End Sub
End Class



Voici le code principal qui implémente le marshaling tel que je le comprends.

Public Module MonModule

Public Delegate Sub ResultatPresent(ByRef T() As Integer, ByVal L As
Integer)

Dim TraitementResultat As New ResultatPresent(AddressOf
TraiteResultatDisponible)

Private Sub TraiteResultatDisponible(ByRef T() As Integer, ByVal Longueur
As Integer)
For i As Integer = 0 To Longueur
Console.Write(T(i).ToString("000") & " ") ' Affichage proprement dit
Next
End Sub

Private Sub ResultatDisponible(ByRef T() As Integer, ByVal Longueur As
Integer)
' TraiteResultatDisponible(T, Longueur) ' Pour test avec appel synchrone
TraitementResultat.BeginInvoke(T, Longueur, Nothing, Nothing) 'Appel
asynchrone
End Sub

Public Sub Main()
Dim Procedure As New MesProcedures(10)
Dim Traitement1 As New Thread(AddressOf Procedure.UneProc1)
Dim Traitement2 As New Thread(AddressOf Procedure.UneProc2)
AddHandler Procedure.ResultatComplet, AddressOf ResultatDisponible
Traitement1.Start() ' Doit fournir les valeurs de 0 à 10
Traitement2.Start() ' Doit fournir les valeurs de 100 à 110
Console.ReadLine() ' Attendre la fin des affichages
End Sub
End Module

Bien sûr, jusque là, il n'y a aucun problème et tout fonctionne.
Il y a événtuellement problème si je me suis complètement fourvoyé dans ma
compréhension du marshaling.
Dans ce cas, il serait utile qu'on me dise où j'ai dérapé …

Par contre, il y a réellement problème si ma compréhension et la mise en
œuvre du marshaling sont correctes.
Car dans ce cas, je ne comprends pas pourquoi Microsoft indique ce
dispositif comme étant nécessaire alors
que cela fonctionne encore mieux en multithreading sans marshaling !!!

Après avoir programmé l'exemple MicroSoft, avec et sans marshaling, j'y ai
placé des points de mesures
(Now.TimeOfDay.ToString) de sorte à évaluer les performances. J'ai aussi
effectué les tests en chargeant
les procédures déléguées de traitements supplémentaires (boucle de 1000000
itérations).

Dans tous les cas (déjà même dans l'exemple MesProcedures ci-dessus), le
marshaling provoque une perte de temps.

Alors, voici la question finale : A quoi bon le marshaling quand on fait du
multithreading ?