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#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    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 Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    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 éclairé
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    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 éclairé
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    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 Expert
    Avatar de Mehdi Feki
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 113
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 113
    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.

  6. #6
    Membre éclairé
    Inscrit en
    Août 2006
    Messages
    381
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 381
    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

+ Répondre à la discussion
Cette discussion est résolue.

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