IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

[2.0][C#]Comment 1 méthode appelant 1 méthode asynchrone peut retourner des données ?


Sujet :

C#

  1. #1
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut [2.0][C#]Comment 1 méthode appelant 1 méthode asynchrone peut retourner des données ?
    Bonjour,

    je possède une classe Acquisition dans laquelle une opération asynchrone est effectuée.
    Cette classe a pour rôle de lire des données dans une carte d'acquisition.
    Cette classe fait parti d'une couche métier.

    Les données lues doivent être affichés sur des graphes placés sur une Window Form.
    Initialement j'avais défini dans ma classe Acquisition deux graphes. Dans le constructeur, j'initialisais les deux graphes avec les références passées en paramètre du constructeur.

    Les données sont lues par une opération asynchrone.
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    m_Reader.BeginReadMultiSample(m_AcquiParametre.SamplesPerChannel, new AsyncCallback(ReadCallBack), null);
    Lorsque l'opération asynchrone est terminée, les données sont lues et affichées sur les graphes.
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
     ReadCallBack(IAsyncResult ar)


    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    /// <summary>
    /// 
    /// </summary>
    public void ReadMultiData()
    {
      if (m_TaskRunning)
      {
         try
         {
           // begin an asynchronous analog input operation
           m_Reader.BeginReadMultiSample, 
     m_AcquiParametre.SamplesPerChannel,
     new AsyncCallback(ReadCallBack), null);
          }
         catch (DaqException ex)
          {}
        }
    }
     
    /// <summary>
    /// 
    /// </summary>
    /// <param name="ar"></param>
    private void ReadCallBack(IAsyncResult ar)
    {
      if (m_TaskRunning)
      {
        try
        {
           //get the data acquired from the asynchronous operation
           Double[,] data = m_Reader.EndReadMultiSample(ar);
     
           if (m_GraphMesBrut != null)
              m_GraphMesBrut.ChartY(data);
     
           if (m_GraphMesScale != null)
               m_GraphMesScale.ChartY(data);
     
           m_Reader.BeginReadMultiSample(1000, new AsyncCallback
    (ReadCallBack), null);
        }
       catch (DaqException ex)
        {}
     }
    }

    Mais cette classe Acquisition devient dépendantes des deux graphes.
    Ce qui est embêtant, vous êtes d'accord n'est ce pas ?

    Si vous êtes d'accord, j'aimerais supprimer ces deux graphes. Et du coup, j'amerais retourner les données lues c'est à dire le tableau double[,] à la classe appelante de la méthode ReadMultiData().
    Mais comment faire pour retourner des données depuis une méthode tel que ReadCallback ?

    J'espère avoir été clair.
    En fait,
    j'aimerais savoir comment retourner des données depuis une méthode IAsyncResult ?

    Merci.

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Points : 1 561
    Points
    1 561
    Par défaut
    Et bien le meilleur moyen de rendre synchrone quelque chose d'asynchrone et vice versa c'est d'utiliser des threads dédiés ou du moins les mécanismes de synchronisation des threads.
    En fait ce que tu va faire, c'est bloquer le thread qui appel une fonction de lecture des données
    et réveillé ce thread quand la méthode asynchrone aura fini son traitement.
    pour cela il y a les objets de synchronisation monitor.
    Ils permettent d'entrer en section critique mais de s'endormir et attendre un signal. A ce moment là ils sortent de section critique et s'endorme. Lorsque la fonction asynch se termine tu la fait entrer dans la section critique sur le meme monitor, et tu lui fait réveiller l'autre après avoir stoquer les données dans une variable interne à la classe. Dès que le thread appelant est réveillé, il lit cette variable sure d'etre le seul a pouvoir y toucher, puisque la fonction asynchrone en lancant le signal a du meme coup perdu la section critique, et retourne le résultat. Ainsi ta fonction retourne un résultat en rendant synchrone un évenement Asynchrone.

    Cela peut dans certains cas ne pas fonctionner correctement. Dans ce cas, il faut créer un thread de synchronisation interne, mais essaye déjà cette technique sans créer de thread, juste en verrouillant le thread appelant. Si ca devait ne pas fonctionner... et bien dit le

  3. #3
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Ok je te remercie, je vais étudier cela.
    Ce qui m'embête est que le thread appelant est celui qui gère mon interface graphique. Si je le mets en position d'attente, mon interface graphique va être gelé.
    Penses-tu qu'il serait judicieux que je lance un évenement quand la lecture est terminée ? Ainsi je ne bloque pas le thread courant...

    Merci.

  4. #4
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Quelqu'un aurait-il d'autres idées pour qu'une méthode appelant une méthode asynchrone puisse retourner des données ?

    Par exemple,

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    public class Program
    {
         public static void Main()
         {
                 MaClasse maClasse = new MaClasse();
     
                 maClasse.ReadASynchronous();
         }
    }
     
    public class MaClasse
    {
        Byte[] m_Tampon = new Byte[500];
        NetworkStream m_NetworkStream;
     
         public void ReadASynchronous()
         {
              m_NetworkStream.BeginRead(m_Tampon, 0, m_Tampon.Length, new AsyncCallback(this.OnLectureFini, null);
         }
     
            /// <summary>
            /// Procédure de finalisation de la lecture
            /// </summary>
            /// <param name="asyncResult"></param>
            private void OnLectureFini(IAsyncResult asyncResult)
            {
               // Doit retourner des données à la méthode appelante.
            }      
    }

    Comment puis-je faire ?

    Merci.

  5. #5
    Membre expérimenté
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Points : 1 566
    Points
    1 566
    Par défaut
    Je ne sais pas il est de quel type ton reader, mais je vais prendre l'exemple d'un FileStream :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length, null, null);
     
    // Faire un travail en parallele
     
    // L'appel de  EndRead va bloquer jusqu'à ce que the Async termine le travail
    int numBytes = strm.EndRead(result);

    Autre maniere :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // Verifier si le travail est terminé
    while (!result.IsCompleted)
    {
        //faire un travail en paralelle.
        Thread.Sleep(100);
    }

    Mais bon si tu peux être plus clair ou donner un exemple par rapport à la classe Stream, je pourrais eut être t'aider d'avantage.
    Mehdi Feki : Modérateur .Net

  6. #6
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Hello,

    merci pour la réponse,

    je vais tâcher d'être plus clair:

    dans le cas synchrone une méthode retourne des données par le paramètre de retour.
    Par exemple:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public static void Main()
    {
       string chaine ;
     
        MaClasse maClasse = new MaClasse();
     
        chaine = maClasse.ReadData();
    }

    Par contre, si dans la fonction ReadData, une fonction asynchrone est utilisée je ne sais pas comment ReadData peut retourner des données dans la fonction Main.

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public static void Main()
    {
         string chaine;
         MaClasse maClasse = new MaClasse();
     
         maClasse.ReadData();
    }

    avec MaClasse:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    public MaClasse
    {
             Byte[] m_Tampon = new Byte[500];
        NetworkStream m_NetworkStream;
     
         public void ReadData()
         {
              m_NetworkStream.BeginRead(m_Tampon, 0, m_Tampon.Length, new AsyncCallback(this.OnLectureFini, null);
         }
     
            /// <summary>
            /// Procédure de finalisation de la lecture
            /// </summary>
            /// <param name="asyncResult"></param>
            private void OnLectureFini(IAsyncResult asyncResult)
            {
                int nOctets = m_NetworkStream.EndRead(result);
     
                if (nOctets > 0)
                 {
                     // Acquisition des données émises par le serveur
                     string sChaineLue = Encoding.ASCII.GetString(m_Tampon, 0, nOctets);
                }
            }  
    }

    Là par exemple, commen retourner la chaîne lue à la méthode appelante depuis la classe main ?

    Est-ce qu'il faut que dans la classe MaClasse un évenement soit lancé lorsque la procédure de finalisation est appelée ? (Vu que j'ai une fâcheur tendance à utiliser les evenements, je ne pense pas que ce soit ça)

    Est-ce qu'il faut que l'appel à la méthode ReadData soit fait aussi dans la classe main de manière asynchrone ?

    Est-ce qu'il faut faire de la synchronisation de threads ?

    Merci d'avance pour le coup de main.
    Bye

  7. #7
    Membre expérimenté
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Points : 1 566
    Points
    1 566
    Par défaut
    En asynchrone il existe trois maniere de faire. Ca s'appelle les models rendez-vous

    Wait-Until-Done Model
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length, null, null);
     
    // Faire un travail en parallele
     
    // L'appel de  EndRead va bloquer jusqu'à ce que the Async termine le travail
    int numBytes = strm.EndRead(result);

    Polling Model
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    // Faire l'appel asynchrone
    IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length, null, null);
    // Verifier si le travail est terminé
    while (!result.IsCompleted)
    {
        //faire un travail en paralelle.
        Thread.Sleep(100);
    }
    // Si on est ici alors le Async a terminé son travail
    int numBytes = strm.EndRead(result);

    Callback Model : avec événement comme tu dis

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length,
            new AsyncCallback(CompleteRead), strm);
    void CompleteRead(IAsyncResult result)
    {
     
        FileStream strm = (FileStream) result.AsyncState;
        int numBytes = strm.EndRead(result);
    }

    Je connais pas d'autres modéls, maintenant ca dépend de ton besoin tu peux choisir le model qui te convient.
    Mehdi Feki : Modérateur .Net

  8. #8
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Bonsoir,

    je te remercie pour tous ces modèles, je n'en connaissais pas l'existence. J'ai toujours utilisé le dernier modèle pour l'asynchrone.
    Mais pour être plus précis, j'aimerai savoir la chose suivante.
    Je vais prendre un exemple de manière à être plus clair.

    Soit une classe MaClasse qui présente deux méthodes publiques.

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class MaClasse
    {
        // Le traitement consiste à récupérer une chaîne de manières synchrone
        // sur le réseau en utilisant les sockets
        public string ReadSynchronousData()
        {
              String chaine;
              // Traitement
              return chaine;
        }
     
        // Le traitement est similaire mais il consiste à récupérer de manière
        // asynchrone une chaîne de caractères toujours en utilisant les sockets
        public void ReadAsynchronousData()
        {
              strm.BeginRead(buffer, 0, buffer.Length,
            new AsyncCallback(CompleteRead), strm);
        }
     
         void CompleteRead(IAsyncResult result)
         {  
               string chaine;
     
               FileStream strm = (FileStream) result.AsyncState;
               int numBytes = strm.EndRead(result);
     
               // Traitement
     
               // return chaine; Ne peut pas fonctionner
         }
    }

    Maintenant supposons qu'il y ait une méthode satic Main:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    public class Program
    {
         public static void Main()
         {
                 MaClasse obj = new MaClasse();
     
                 // Utilisation de la méthode ReadSynchronousData
                 string chaine = obj.ReadSynchronousData();
     
                 // Meme chose mais avec la méthode ReadAsynchronousData
                 // Comment faire pour récupérer la chaine lue ?
                 string chaine2 = string.empty;
                 obj.ReadAsynchronousData();
         }
    }

    Voilà en fait ma question porte surtout comme c'est précisé en commentaires dans la classe Main sur le moyen de récupérer la chaîne lue.

    Merci d'avance.
    Bye.

  9. #9
    Membre expérimenté
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Points : 1 566
    Points
    1 566
    Par défaut
    Il suffit juste d'appliquer les modeles sur la classe MaClasse, par exemple pour ce que tu propose, la solution serait d'exporter le résultat dans une propriété.

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    public class MaClasse {  
     
    private  byte[] buffer = new byte[100];
     
    private  string _result;
     
    	public string Result
    	{
    		get { return _result;}
     
    	}
     
     public void ReadAsynchronousData()  
    { 
     strm.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(CompleteRead), strm); 
    }   
     
    void CompleteRead(IAsyncResult result) 
     { 
    string chaine;   
    FileStream strm = (FileStream) result.AsyncState; int numBytes =  int numBytes = strm.EndRead(result);
     
    strm.Close();
    _result = BitConverter.ToString(buffer);
    } 
    }
    Mehdi Feki : Modérateur .Net

  10. #10
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Bonsoir,

    ok mais ensuite comment prévenir la classe Main que la valeur de la propriété a été mise à jour ?

    Merci bien.

  11. #11
    Membre expérimenté
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Points : 1 566
    Points
    1 566
    Par défaut
    Citation Envoyé par Pilloutou
    Bonsoir,

    ok mais ensuite comment prévenir la classe Main que la valeur de la propriété a été mise à jour ?

    Merci bien.
    Un petit booleén par exemple.

    sinon utilise les 2 premiers models.
    Mehdi Feki : Modérateur .Net

  12. #12
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Bonsoir,

    donc avec le premier modèle, cela donnerait:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class MaClasse
    {
         [..]
         public string ReadAsynchronousData()
         {
              IAsyncResult result = strm.BeginRead(buffer, 0, buffer.Length, null, null);
             // Appel de  EndRead
             int numBytes = strm.EndRead(result);
             [..]
             // Retour de la chaîne lue
             return chaine;
         }
    }

    Avec le deuxième cela donnerait quelque chose de similaire.
    Par contre, avec ces modèles ne perd-on pas l'interêt de l'utilisation asynchrone ?
    En effet, l'appel va être bloquant tant que la valeur n'est pas retournée.

    Pour le booleen je ne suis pas sûr d'avoir compris.
    Est-ce que tu pensais à quelque chose comme ça ?

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class MaClasse {  
     
    private  byte[] buffer = new byte[100];
     
    private  string _result;
     
    	public string Result
    	{
    		get { return _result;}
     
    	}
     
    private bool m_Flag;
    public bool Flag
    {
        get{return m_Flag;}
        set{
             if (m_Flag!=value)
                 m_Flag = value;
         }
    }
     
     public void ReadAsynchronousData()  
    { 
     strm.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(CompleteRead), strm); 
    }   
     
    void CompleteRead(IAsyncResult result) 
     { 
    string chaine;   
    FileStream strm = (FileStream) result.AsyncState; int numBytes =  int numBytes = strm.EndRead(result);
     
    strm.Close();
    _result = BitConverter.ToString(buffer);
     
    // La valeur a été modifiée
    // Le flag est mis à 1
    m_Flag = true;
     
    }
    }

    et dans la classe MaClasse:
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public class Program
    {
          public static void Main()
          {
               MaClasse obj = new MaClasse();
               obj.ReadAsynchronousData();
               while (!obj.Flag)
               {
               }
               string chaine = obj.Result;
                obj.Flag = false;
          }
    }


    Et que penses-tu de ces méthodes ?


    L'évenement:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class MaClasse
    { 
          // Evenement lancé lorsque la chaine a été lue
          public event EventHandler ChainePret;
     
          private  byte[] buffer = new byte[100];
     
    private  string _result;
     
    	public string Result
    	{
    		get { return _result;}
     
    	}
     
    public void ReadAsynchronousData()  
    { 
     strm.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(CompleteRead), strm); 
    }   
     
    void CompleteRead(IAsyncResult result) 
     { 
    string chaine;   
    FileStream strm = (FileStream) result.AsyncState; int numBytes =  int numBytes = strm.EndRead(result);
     
    strm.Close();
    _result = BitConverter.ToString(buffer);
     
    // La valeur a été modifiée
    // Lancement de l'évenement
    OnChainePret(new EventArgs());
     
    }
     
    private void OnChainePret(EventArgs ev)
    {
         if (ChainePret != null)
               ChainePret(this,ev);
    }
    }

    et dans la classe Main:
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    public class Main
    {
        public static void Main
        {
             MaClass obj = new MaClasse();
             obj.ChainePret += new EventHandler(ChaineRecue);
             obj.ReadAsynchronousData();
        }
     
        void ChaineRecue(object sender, EventArgs e)
        {
             // La chaine est prête:
             MaClasse obj = sender as MaClasse;
     
             string chaine = string.empty;
             if (obj != null)
                 chaine = obj.Result;
     
        }
    }

    Qu'en penses-tu ?

    Après il y a aussi la synchronisation de thread:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class MaClasse
    {
         [..]
     
         static AutoResetEvent ev;
     
         public void ReadComplete(IAsyncResult ar)
         {
                ev.set();    
         }
    }
     
    public class Program{
     
    public static void Main()
    {
            MaClass obj = new MaClasse();
            obj.ReadAsynchronousData();
            obj.ev.WaitOne();
            string chaine = obj.Result;
    }
     
    }

    Qu'en penses-tu ?

    Merci pour tes bons conseils.

    Bye

  13. #13
    Membre expérimenté
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Points : 1 566
    Points
    1 566
    Par défaut
    Pour le flag oui, c'est de ca dont je parlais.

    Sinon pour le premier model c'est plutot comme ca :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    //une nouvelle méthode qui bloque jusqu'à la fin
     public string EndAsynchronousRead()  
    { 
    string chaine;   
    FileStream strm = (FileStream) result.AsyncState;
     
    //result est declaré dans les membres de la classe
    int numBytes = strm.EndRead(result);
     
    strm.Close();
    return BitConverter.ToString(buffer);
    }

    Pour l'utilisation de l'evenement c'est aussi une bonne idée mais quel est l'interet,si le main ne recupere plus l'information traitée dans ce cas laisse MaClasse faire tout le boulot.

    La meme chose pour la synchronisaion, je pense que tu es entrain de reproduire le premier model
    Mehdi Feki : Modérateur .Net

  14. #14
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Ok et merci,

    le main était juste là pour l'exemple.
    Disons que la référence vers la classe MaClasse pourrait être dans une autre classe.

    Malgrès tout, l'avantage d'utiliser un évenement est que cela ne bloque pas le thread courant en attendant l'execution de la méthode de finalisation contrairement aux autres solutions. Pas d'accord ?

    Bye

  15. #15
    Membre expérimenté
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Points : 1 566
    Points
    1 566
    Par défaut
    Oui mais ton programme main ne control plus la fin de thread. Pourquoi faire de l'asynchrone dans ce cas
    Mehdi Feki : Modérateur .Net

  16. #16
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    En fait la classe Main était là pour l'exemple.

    J'ai une Windows Forms qui doit afficher des données venant d'un serveur de socket. Ce serveur renvoie les données toutes les deux secondes.
    Ainsi la classe gérant les échanges avec ce serveur:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class EchangeServeurSocket
    {
         private Data m_Info;
         public Data Info
         {
             get { return m_Info; }
         }
     
          public void ReadAsynchronousData()
          {
                 m_NetworkStream.BeginRead(m_Tampon, 0, m_Tampon.Length, new AsyncCallback(this.OnLectureFini, null);
          }
     
            /// <summary>
            /// Procédure de finalisation de la lecture
            /// </summary>
            /// <param name="asyncResult"></param>
            private void OnLectureFini(IAsyncResult asyncResult)
            {
                int nOctets = m_NetworkStream.EndRead(result);
     
                if (nOctets > 0)
                {
                     // Acquisition des données émises par le serveur
                     string sChaineLue = Encoding.ASCII.GetString(m_Tampon, 0, nOctets);
                     // Découpage de cette chaîne
                     // Récupération des données et mise à jour
                     // Chaque donnée est séparée par des ;
                     // Valeur d'intensité:
                     m_Info.Intensite = [..];
     
                     // Valeur de la tension
                     m_Info.Tension = [..];
     
                     // etc.
     
                    // Rappel de la méthode de lecture
                    ReadAsynchronousData();
     
                  // La valeur a été modifiée
                  // Lancement de l'évenement
                   OnChainePret(new EventArgs());
     
                   }
              }
     
              private void OnChainePret(EventArgs ev)
              {
                    if (ChainePret != null)
                          ChainePret(this,ev);
              }
    }

    et l'interface utilisateur:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class UIData:Form
    {
         private EchangeServeurSocket echange;
     
         public UIData()
         {
                   echange = new EchangeServeurSocket();
     
                   echange.ChainePret += EventHandler(DonneeModifie);
         }
     
        void DonneeModifie(object sender, EventArgs e)
        {
             // La chaine est prête:
             Data info = echange.Info;
     
             // Mise à jour des contrôles utilisateurs
     
        }
    }

    Ainsi, l'interface utilisateur qui ne fait pas qu'afficher des données, n'est pas gelée.
    Qu'en penses-tu maintenant ?

    Mais les évenements, j'entends et lis que ce n'est pas tellement conseille parce que c'est de la spaghettisation de code et j'essaie de m'en passer.

    Merci
    Bye

  17. #17
    Membre expérimenté
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Points : 1 566
    Points
    1 566
    Par défaut
    Dans ce cas c'est une solution que tu pourra eviter en faisant de simples threads :
    Mettre à jour l'IHM pendant un traitement.
    Mehdi Feki : Modérateur .Net

  18. #18
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    J'ai lu le document que tu m'as laissé en URL.

    Pourrais-tu me montrer avec mon code, parce que je n'arrive pas trop à voir comment faire avec mon cas.

    Merci d'avance pour l'aide.

  19. #19
    Membre expérimenté
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    Points : 1 566
    Points
    1 566
    Par défaut
    Un Truc de ce genre :

    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
     public partial class Form1 : Form
        {
            private delegate void TextBoxDelegateHandler(string text);
            private TextBoxDelegateHandler TextBoxDelegate;
     
            public Form1()
            {
                InitializeComponent();
                TextBoxDelegate = new TextBoxDelegateHandler(UpdateTextBox);
            }
     
            private void button1_Click(object sender, EventArgs e)
            {
                Thread t = new Thread(new ThreadStart(ThreadProcess));
                t.Start();
            }
     
            private void ThreadProcess()
            {
               // tu lis ta chaine normalement sans les méthodes asnychrone
                string result=File.ReadAllText(@"C:\MonText.txt");
                this.Invoke(this.TextBoxDelegate, new object[] { result });
            }
     
            private void UpdateTextBox(string text)
            {
                textBox1.Text = text;
            }
     
        }
    Mehdi Feki : Modérateur .Net

  20. #20
    Membre actif
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    Points : 252
    Points
    252
    Par défaut
    Donc cela donnerait pour mon cas:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    public class EchangeServeurSocket
    {
     
          public Data ReadContinuous()
          {
                 m_NetworkStream.BeginRead(m_Tampon, 0, m_Tampon.Length, null, null);
                 int nOctets = m_NetworkStream.EndRead(IAsyncResult result);
     
                 Data info = null;
     
                 if (nOctets > 0)
                {
                     // Acquisition des données émises par le serveur
                     string sChaineLue = Encoding.ASCII.GetString(m_Tampon, 0, nOctets);
     
                     info = new Data();
     
                     // Découpage de cette chaîne
                     // Récupération des données et mise à jour
                     // Chaque donnée est séparée par des ;
                     // Valeur d'intensité:
                     info.Intensite = [..];
     
                     // Valeur de la tension
                     info.Tension = [..];
     
                     // etc.
                 }
                 return info;
          }
    }

    Mais dans ce cas, je ne vois pas trop l'interet de faire une lecture asynchrone puisque l'appel est bloqué.

    et l'interface utilisateur:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class UIData:Form
    {
         private EchangeServeurSocket echange;
     
         private Thread th;
     
         public UIData()
         {
                   echange = new EchangeServeurSocket();
     
                   th = new Thread(new ThreadStart(GetData));
     
                   th.Start();
         }
     
         private void GetData()
         {
                // La lectue doit être continue
                while (true)
                {
                        Info data = echange.ReadContinuous();
     
                        // Mise à jour des contrôles
     
                }
         }
    }

    Qu'en penses-tu ?

    Le souci est que j'aurais aimé que la lecture continue soit faite dans la classe EchangeServeurSocket parce que je trouve cela plus logique

    Comme ceci:

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class EchangeServeurSocket
    {
         private Data m_Info;
         public Data Info
         {
             get { return m_Info; }
         }
     
          public void ReadContinuous()
          {
                 m_NetworkStream.BeginRead(m_Tampon, 0, m_Tampon.Length, new AsyncCallback(this.OnLectureFini, null);
          }
     
            /// <summary>
            /// Procédure de finalisation de la lecture
            /// </summary>
            /// <param name="asyncResult"></param>
            private void OnLectureFini(IAsyncResult asyncResult)
            {
                int nOctets = m_NetworkStream.EndRead(result);
     
                if (nOctets > 0)
                {
                     // Acquisition des données émises par le serveur
                     string sChaineLue = Encoding.ASCII.GetString(m_Tampon, 0, nOctets);
                     // Découpage de cette chaîne
                     // Récupération des données et mise à jour
                     // Chaque donnée est séparée par des ;
                     // Valeur d'intensité:
                     m_Info.Intensite = [..];
     
                     // Valeur de la tension
                     m_Info.Tension = [..];
     
                     // etc.
     
                    // Rappel de la méthode de lecture
                    ReadContinuous();
                   }
              }
    }

    Merci en tout cas pour ton aide et tes conseils.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 3
    Dernier message: 20/01/2005, 19h19
  2. CFile : comment lire des données
    Par romeo9423 dans le forum MFC
    Réponses: 3
    Dernier message: 25/10/2004, 19h10
  3. Réponses: 23
    Dernier message: 22/04/2004, 11h55
  4. Comment récuperer des données entrées au clavier?
    Par Elisée A. dans le forum MFC
    Réponses: 2
    Dernier message: 13/02/2004, 07h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo