Comment convertir un appel de délégué en ligne lorsque l'on convertit du code CSharp en VB.Net ?

De ORSWiki
Aller à : navigation, rechercher

Au départ, il s'agit par exemple de corriger l'erreur classique inter-threads :

"Opération inter-threads non valide : le contrôle 'lblStatus' a fait l'objet d'un accès à partir d'un thread autre que celui sur lequel il a été créé."

Le code en C# est le suivant : www.codeproject.com/KB/cs/ApplicationIdle.aspx

   private void App_Idle(ApplicationIdleTimer.ApplicationIdleEventArgs e)
   {
       this.lblStatus.BackColor = Color.Green;
       this.lblStatus.Text = string.Format("Idle: {0}s", e.IdleDuration.TotalSeconds.ToString("0"));
   }

La solution en C# est d'utiliser un délégué, ici déclaré directement en ligne dans le code :

   private void App_Idle(ApplicationIdleTimer.ApplicationIdleEventArgs e)
   {
       Invoke((MethodInvoker) delegate
       {
           lblStatus.BackColor = Color.Green;
           lblStatus.Text = string.Format("Idle: {0}s", e.IdleDuration.TotalSeconds.ToString("0")); 
       });
   }

Lorsque l'on utilise le convertisseur de code de C# en VB.Net, on obtient un code qui ne compile pas :

www.developerfusion.com/tools/convert/csharp-to-vb/

   Invoke(DirectCast(Function() Do
       lblStatus.BackColor = Color.Green
       lblStatus.Text = String.Format("Idle: {0}s", e.IdleDuration.TotalSeconds.ToString("0"))
   End Function, MethodInvoker))
   

Voici comment il faut corriger ce code :

Il faut d'abord déclarer un délégué perso.:

   Public Delegate Function myDelegate( _
       ByVal e As ApplicationIdleTimer.ApplicationIdleEventArgs) As Integer
   

Ensuite il faut déclarer une fonction perso. qui sera appelée par le délégué :

   Function MyFunctionDelegate(ByVal e As ApplicationIdleTimer.ApplicationIdleEventArgs) As Integer
       lblStatus.BackColor = Color.Green
       lblStatus.Text = String.Format("Idle: {0}s", e.IdleDuration.TotalSeconds.ToString("0"))
       Return 0
   End Function
   

Et enfin il faut faire appeler la fonction perso. via le délégué depuis la fonction principale qui est appelée par l'autre thread, de sorte qu'au final, ce sera bien le thread associé à la fenêtre principale qui affichera ce qu'il faut :

   Private Sub App_Idle(ByVal e As ApplicationIdleTimer.ApplicationIdleEventArgs)
       Dim myDel As New myDelegate(AddressOf MyFunctionDelegate)
       Dim args() As Object = {e}
       MyBase.Invoke(myDel, args)
   End Sub