Traitement asynchrone : exemple de function delegate avec passage de paramêtres

Soyez le premier à donner votre avis sur cette source.

Vue 16 766 fois - Téléchargée 790 fois

Description

Je voudrais faire de l'asynchrone pour lancer les traitement bdd, report ou autre qui bloquent l'écran.
Mais je me suis rendu compte que c pas si simple. Donc j'ai du me faire un petit example à part pour avoir une idée clair de la démarche :

1. déclarer une fonction delegate et la fonction même signature (TestDelegateSimple et FunctionAsynchroneSimple);

2. déclarer les Callback et beginInvoke (dans Sub Start) pour executer sur un autre thread

3. Récupérer les infos en fin de traitement du thread avec EndInvoke (dans Sub AsyncInfo)

4. Passage de paramètre et récupération des erreurs.

J'affiche dans me.Label1 le suivi du traitement. Il montre que l'on récupère bien les modifications faite dans la fonction asynchrone.
Ca marche mais je ne sais pas comment traiter 'proprement' les erreurs survenues dans le Thread asynchrone.
Je continue à chercher mais j'espère que l'un de vous pourra m'aider !

Source / Exemple :


Option Explicit On 
Option Strict On

Public Class frmTestDelegate
	Inherits System.Windows.Forms.Form
	Public Delegate Function TestDelegateSimple(ByRef info As String) As InfoThread

#Region " Windows Form Designer generated code "
'Cette partie est dans le zip.
... 

	Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
		Start()
		Me.Label1.Text += vbCrLf + "Button1 Fini"
		Dim i As Int32
		Dim y As Int32 = 10000000
		Me.Label1.Text += vbCrLf + " en attendant ..."
		For i = 0 To y * 100
			If i Mod y = 0 Then
				Me.Label1.Text += " " + CStr(i / y)
				Application.DoEvents()
			End If
		Next
	End Sub

	'lance le traitement asynchrone 
	Private Sub Start()
		Dim cb As AsyncCallback = New AsyncCallback(AddressOf AsyncInfoEnd)
		Dim d As TestDelegateSimple = New TestDelegateSimple(AddressOf FunctionAsynchroneSimple)
		Dim infoEnter As String = "Debut Thread"
		Dim i As InfoThread
		Try
			d.BeginInvoke(infoEnter, cb, "Deb")
		Catch
			Debug.Assert(False)
		End Try
	End Sub

	'Les traitement asynchrones se font ici...
	Shared Function FunctionAsynchroneSimple(ByRef info As String) As InfoThread
		'Mais je ne sais pas récupérer les erreurs !!! HELP !!!
		Try
			'Ligne suivante pour provoquer une erreur :
			'Dim tb As Int16() : ReDim tb(1) : tb(0) = 0 : tb(1) = 1 : tb(2) = 2
			System.Threading.Thread.CurrentThread.Sleep(New TimeSpan(0, 0, 5))
			'MessageBox.Show("terminé")
			Dim iTh As New InfoThread()
			ith.Texte = "Boucle asynchrone fini"
			Return iTh
		Catch ex As Exception
			Dim ith As New InfoThread()
			ith.ITException = ex
			Return ith
		End Try
		'MsgBox(info)
	End Function

	'Function de fin de traitement.
	Public Sub AsyncInfoEnd(ByVal ar As System.IAsyncResult)
		If ar.CompletedSynchronously Then
			'keskifé ?
		ElseIf ar.IsCompleted Then
			Dim value As String = Convert.ToString(ar.AsyncState)
			Dim Async As System.Runtime.Remoting.Messaging.AsyncResult
			Async = CType(ar, System.Runtime.Remoting.Messaging.AsyncResult)
			Dim tmp As TestDelegateSimple = CType(Async.AsyncDelegate, TestDelegateSimple)
			Dim result As InfoThread = tmp.EndInvoke("tmp", ar)
			'ITException contient l'erreur survenue dans la fonction asynchrone.
			If IsNothing(result.ITException) Then
				Me.Label1.Text += vbCrLf + "IsCompleted : " + value + " -> " + result.Texte + vbCrLf
			Else
				Me.Label1.Text += vbCrLf + "IsCompleted : " + value + " -> " + result.ITException.ToString + vbCrLf
			End If
			'On peut ajouter des testes sur ar pour voir l'état du thread.
		End If

	End Sub

End Class

'Classe passée en param pour les infos du Thread.
Public Class InfoThread
	Public Texte As String	 'L'objet dont ont veut récupérer l'état et qui est long à répondre et que ça vaut le coup de se casser le c. de faire tout ça.
	Public ITException As Exception	'ex survenue dans l'autre Thread.
End Class

Conclusion :


Gestion d'erreur "maison" ! C'est pas propre mais si qq1 a mieux ... je suis prenneur.

Codes Sources

A voir également

Ajouter un commentaire Commentaire
blq Messages postés 97 Date d'inscription vendredi 22 octobre 1999 Statut Membre Dernière intervention 13 juin 2016 1
18 sept. 2011 à 17:17
Il y a encore certains points sur le Thread qui m’échappent pour mon niveau de débutant, mais je me suis inspiré de ce code pour faire un passage de multiples arguments à une fonction exécutée en Thread. Merci donc pour cet exemple qui mériterait tout de même plus de détails en explication.

Il y a par exemple l'appel : Dim result As InfoThread = tmp.EndInvoke("tmp", ar)
Je comprend que la première variable corresponde à la fonction TestDelegateSimple, mais "tmp" semble ne servir à rien ?
C'est une bonne interrogation dans mon cas, car ma fonction Delegate utilise plusieurs paramètres et dans mon programme l'équivalent ne nécessite que : Dim result As InfoThread = tmp.EndInvoke(ar)
Si je supprime "tmp" dans ton code, j'ai bien évidement une erreur. Il y a donc un point qui m'a échappé dans mon code qui ne génère pas d'erreur...

Dernier point, dans mon cas VB Express 2010, la fonction plante en fin de traitement sur :
Me.Label1.Text += vbCrLf + "IsCompleted : " ...

Label1 n'est pas accessible et ne fait pas partie du Thread. Pourquoi ?... Mes connaissances ne sont pas assez bonnes pour y répondre, mais ce n'est pas l'essentiel, si on souhaite juste appréhender le lancement du Thread avec paramètres.

Il me reste à trouver le moyen de faire attendre un Thread à la libération d'une ressource commune... J'aurais surtout besoin d'un bon Tuto dans ce domaine. je vais chercher dans les autres sources :-)

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.