Problème affichage Label suite a Invoke [Résolu]

Signaler
-
 Utilisateur anonyme -
--------------------------------------------------------------------------------

Bonjour,

Je développe actuellement une application qui communique avec une balance via le port RS232.

Pour cela j'ai créé une classe de Balance qui manipule un objet SerialPort.
La communication fonctionne bien. Les données sont bien récupérées.

Après avoir récupéré les données je souhaite les afficher dans un WinForm au travers d'un label. J'ai vérifié le label possède bien la bonne valeur dans sa propriété Text mais il n'est pas visible sur l'interface utilisateur (pourant le visible est a True). Il s'agit surement d'un problème de gestion de Thread mais je n'arrive pas a comprendre d'où cela provient.

Voici le code de ma classe Balance :

 
Imports System.IO.Ports
Imports System.Windows.Forms
 
Public Class Balance
    Private comPort As SerialPort
 
    'control dans lequel on veux afficher le résultat'
    Private _display As Control
    Private Delegate Sub SetTextCallback(ByVal text As String)
 
 
    Public Property Display() As Control
        Get
            Return _display
        End Get
        Set(ByVal value As Control)
            _display = value
        End Set
    End Property
 
 
    'initialisation du port COM'
    Public Sub New()
        comPort = New SerialPort
        comPort.PortName = "COM1"
        comPort.Parity = IO.Ports.Parity.None
        comPort.BaudRate = 9600
        comPort.StopBits = IO.Ports.StopBits.One
        comPort.RtsEnable = True
 
        AddHandler comPort.DataReceived, AddressOf dataReceived
 
    End Sub
 
    'Ouverture du port COM'
    Public Sub Open()
        If Not comPort.IsOpen Then
            comPort.Open()
        End If
    End Sub
 
 
    'Fermeture du port COM'
    Public Sub Close()
        If comPort.IsOpen Then
            comPort.Close()
        End If
    End Sub
 
 
    'Demande de récupération de la pesé sur la balance'
    Public Sub Peser()
        comPort.Write("PRT" & Chr(13) & Chr(10))
    End Sub
 
    'Procédure éxécuté quand la balance répond'
    Private Sub dataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
        Dim mess As String = comPort.ReadExisting()
 
        'Permet de formater la valeur afin d enlever les caractère indésiable (signe, unité, blanc)'
        Dim nb As Integer
        For Each c In mess
            If Not Integer.TryParse(c, nb) Then
                If c <> "." Then
                    mess = mess.Replace(c, "")
                End If
            End If
        Next
        mess = mess.Trim
 
        'on souhaite afficher le résultat' 
        DisplayData(mess)
 
    End Sub
 
    'procédure qui permet affichage dans le control souhaité'
    Private Sub DisplayData(Text As String)
        If _display.InvokeRequired Then
            _display.Invoke(New SetTextCallback(AddressOf DisplayData), New Object() {(Text)})
        Else
            _display.Text = Text
        End If
    End Sub
 
 
End Class


Avez vous une idée ?

26 réponses

Merci beaucoup banana32. Je trouve ce code très propre il me plait. Je l'ai appliqué dans mon application et ça fonctionne très bien.

Me reste plus qu'a trouver une solution au cas : Aucune donnée n'est retourné.
Je pense qu'un timer dans la winform devrait suffir pour ce point.

A bientot
J'ai implémenté le Timer dans la dll et c'est parfait.

Merci vraiment pour tout ces conseil bien utile.
J'ai un autre petit soucis...

Je n'arrive pas à faire fonctionner 2 timer en même temps.

Le premier Timer est celui qui me sert a gérer le temps d'attente trop long donc il est déclenché dès que j'envoi la commande à la balance et lève un evenement NoDataReceived sur son tick.

Le deuxième permet d'attendre un temps donné après le premier passage dans le dataReceived afin d'être sur que toute les données sont arrivées.

Le premier fonctionne bien mais le deuxième ne tick pas pourtant on passe bien dans le dataReceived j'ai mis une condition afin d'éviter de le réactiver à chaque passage dans dataReceived.

Au niveau des temps d'attente j'ai mis 500 par default pour attente de la réponse complète et 500 de plus pour levé l'evenement qui indique qu'aucune données n'a été reçu.

Procédure dataReceived la balance répond :
    'Procédure éxécuté quand la balance répond
    Private Sub dataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
        'on laisse les données arrivé pendant timeToWait
        If Not timerDataReceivedStart Then
            timerDataReceivedStart = True
            timerDataReceived.Start()
        End If
    End Sub


Tick du timer d'attente de réponse complète.
Private Sub timerDataReceived_Tick(sender As Object, e As EventArgs)
        timerDataReceived.Stop()
        timerAttenteMax.Stop()

        If control.InvokeRequired Then
            control.Invoke(New timerDataReceivedCallBack(AddressOf timerDataReceived_Tick), sender, e)
        Else
            Dim mess As String = comPort.ReadExisting()

            Dim nb As Integer
            For Each c In mess
                If Not Integer.TryParse(c, nb) Then
                    If c <> "." Then
                        mess = mess.Replace(c, "")
                    End If
                End If
            Next
            mess = mess.Trim

            Dim ev As New PoidsReceivedEventArgs(Decimal.Parse(mess))
            RaiseEvent PoidsReceived(Me, ev)

        End If
    End Sub


avez vous une idée de pourquoi ce timer ne veux pas faire Tick ? Une histoire de thread ?

On ne voit pas certaines parties de ton code. Ta sub timerDataReceived_Tick gérant le Tick est dépourvue de l'instruction Handles timerDataReceived.Tick.
Je suppose que tu abonnes ton timer dynamiquement à l'événement avec l'instruction AddHandler quelque part ailleurs ?
Oui, excuse moi j'ai oublié de préciser que l'abonnement se faisait dans le constructeur de ma classe Balance.

Content que tu ai pu résoudre ton problème

ce n'est plus Tick mais Elapsed
C'est pourtant ce que qui apparaît dans mon exemple plus haut.
Private Sub tmr_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles tmr.Elapsed

C'est vrai que la confusion était facile. Désolé de ne pas avoir pensé à préciser ce point.

Bonne journée.
1 2