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 :

Problème de synchronisation avec un callback par du code non managé ?


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2005
    Messages : 346
    Points : 119
    Points
    119
    Par défaut Problème de synchronisation avec un callback par du code non managé ?
    Bonjour,

    J'ai un problème avec le remplissage d'un buffer (ressource managée) par du code non managé.
    Au bout d'un moment, les valeurs récupérées dans le buffer sont nulles alors qu'elles ne devraient pas.
    Selon le Sleep([DELAY]) que j'utilise dans une boucle while, le buffer se remplit plus ou moins bien.

    Je suppose donc qu'il s'agit d'un problème de synchronisation...

    Autre piste: problème d'objet déplacé par le ramasse-miettes ? Je dis peut-être une grosse bêtise mais mon buffer étant un type référence (tableau de valeurs primitives), j'ai lu que le ramasse-miette était susceptible de déplacer ce type d'objet en mémoire. Or s'il est utilisé par du code non managé, peut-être existe-t-il le risque que le buffer soit déplacé et donc plus accessible par le code non managé ?

    Si je fixe les valeurs initiales de mon buffer à -1, lorsque le problème apparait, je retrouve ces valeurs -1... donc il semble bien que le code non managé appelle le callback en disant que des données ont été renseignées dans le buffer alors que ce n'est pas le cas, ce qui nourrit mon petit doute sur le déplacement de mon buffer dans la mémoire...

    Un spécialiste peut-il me dire si je suis dans le vrai ?

    Voici, en gros, ce que fait mon code:

    - instanciation d'un short[] buffer
    - enregistrement du buffer auprès d'une ressource non managée (SetDataBuffer()).
    - démarrage de la collecte des données par le code non managé, via un callback.
    - Callback: renseigne des variables globales sur la quantité de données copiées dans le buffer par le code non managé.
    - Fin de la collecte après collecte d'un certain nombre de valeurs.

    Voici le code de la méthode principale qui définit le buffer, l'enregistre et lance la collecte :

    Code : 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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
     
     
    public int StreamDataHandler(uint preTrigger, uint count, StreamWriter writer)
            {
                short status;
                int totalCollected = 0;
                PicoDriverException error = null;
                uint sampleCount = BUFFER_SIZE + (uint)( count / _downSamplingRatio );
                short[][] minBuffers = new short[_channelCount][];
                short[][] maxBuffers = new short[_channelCount][];
     
                uint sampleInterval = 1;
     
                #region Prépare les buffers de reception
                for ( int i = 0; i < _channelCount; i++ )
                {
                    minBuffers[i] = new short[sampleCount];
                    maxBuffers[i] = new short[sampleCount];
                    status = Imports.SetDataBuffers
                        (_handle, 
                        (Channel)i, 
                        minBuffers[i], 
                        maxBuffers[i], 
                        (int)sampleCount);
     
                    if ( status != (short)Imports.SetDataBuffersResult.Ok )
                        error = new PicoDriverException(status, "SetDataBuffers");
                }
                #endregion
     
     
                #region Initie la collecte des données en StreamingMode
                _autoStop = false;
                status = Imports.RunStreaming
                    (_handle, 
                    ref sampleInterval, 
                    Imports.ReportedTimeUnits.MicroSeconds,
                    preTrigger,
                    count - preTrigger, // Auto-stop quand on atteint (count/_downSamplingRatio) samples 
                    true, // Active l'auto-stop
                    (uint)_downSamplingRatio,
                    sampleCount); // Taille reelle des buffers
     
                if ( ( status != (short)Imports.RunStreamingResult.Ok ) && ( error == null) )
                    error = new PicoDriverException(status, "RunStreaming");
                #endregion
     
     
                Debug.WriteLine("Collecting in StreamingMode...");
                Debug.Indent();
     
                while ( !_autoStop && !_cancelCollect )
                {
                    /* Boucle jusqu'à ce que des données soient reçues.
                     * GetStreamingLatestValues() appelera le callback dès reception de nouveaux samples.
                     * */
     
                    Thread.Sleep(TIMEOUT_COLLECT);
     
                    lock ( _syncCallback )
                    {
     
                        _ready = false;
     
     
                        status = Imports.GetStreamingLatestValues(_handle, StreamingCallback, IntPtr.Zero);
                        if (( status != (short)Imports.GetStreamingLatestValuesResult.Ok ) && (error == null))
                            error = new PicoDriverException(status, "GetStreamingLatestValues");
     
     
                        if ( _ready && _sampleCount > 0 )
                        {
                            // Rappel: 
                            //la collecte a pu se terminer sans données récupérées (si autoStop levé)
     
                            totalCollected += _sampleCount;
                            for ( uint i = _startIndex; i < ( _startIndex + _sampleCount ); i++ ) // pour chaque sample collecté
                            {
                                for ( int j = 0; j < _channelCount; j++ ) // pour chaque canal d'entree 
                                {
                                    if ( _channelSettings[j].enabled )
                                    {
                                        Debug.Assert(minBuffers[j][i] > 0, "Incohérence probable", "Tension nulle récupérée à l'index " + i.ToString());
     
                                        // Canal d'entrée actif ?
                                        // Ecrit la tension dans le flux.
                                        // Rappel: si la valeur vaut Imports.LOST_DATA_VALUE, il y a un buffer overrun.
                                        int mVmin = adc_to_mv
                                                (minBuffers[j][i],
                                                (int)_channelSettings[(int)( Channel.ChannelA + j )].range);
                                        int mVmax = adc_to_mv
                                                (maxBuffers[j][i],
                                                (int)_channelSettings[(int)( Channel.ChannelA + j )].range);
                                        int mVmean = ( mVmin + mVmax ) / 2;
                                        double mAmp = ( (double)mVmean ).VoltageToIntensity(0.1);
                                        double mWatts = ( (double)mVmean ).VoltageToPower(mAmp);
     
                                        writer.Write
                                            ("{0},{1},{2},{3},{4},{5},{6}\r", // "min ADC Count,min mV,max ADC,max mV,mean mV,I,P\r"
                                            minBuffers[j][i],
                                            mVmin,
                                            maxBuffers[j][i],
                                            mVmax,
                                            mVmean,
                                            mAmp,
                                            mWatts
                                            );
     
                                    }
                                }
                            }
     
     
                            writer.Write("*** " + _sampleCount.ToString() + " samples collected  (" + _startIndex.ToString() + "/" + maxBuffers[(int)Channel.ChannelA].Length.ToString() + ") ***\r");
     
                        } 
                    } // Fin de lock()
     
                } // Fin while
     
                Debug.Unindent();
                Debug.WriteLine("End of collect");
     
     
     
                status = Imports.Stop(_handle);
     
                if (( status != (short)Imports.StopResult.Ok ) && (error == null))
                    error = new PicoDriverException(status, "Stop");
     
                // Remonte l'exception
                if ( error != null )
                    throw error;
     
                if ( !_autoStop )
                {
                    throw new Exception("Data collect aborted");
                }
     
                // Renvoie le nombre de samples collectés
                return totalCollected;
            }
    La méthode Callback :

    Code : 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
     
    private void StreamingCallback(short handle,
                                    int noOfSamples, // nb de samples collectés
                                    uint startIndex, // index du premier sample collecté dans les buffers
                                    short ov,
                                    uint triggerAt,
                                    short triggered,
                                    short autoStop, // 1/0: auto-stop ?
                                    IntPtr pVoid)
            {
                Debug.Indent();
                Debug.WriteLine("Callback In");
     
                lock ( _syncCallback )
                {
                    // used for streaming
                    _sampleCount = noOfSamples;
                    _startIndex = startIndex;
                    _autoStop = ( autoStop != 0 );
     
                    // flag to say done reading data
                    _ready = true;
     
                    //Debug.WriteLine(_sampleCount.ToString() + " samples collected");
                }
     
                Debug.WriteLine("Callback Out (_startIndex)");
                Debug.Unindent();
            }
    J'espère avoir donné assez d'infos pour que quelqu'un puisse m'aider ?
    (il s'agit de récupération de valeurs de tension mesurée par un oscilloscope).

    Merci d'avance pour toute aide.

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Août 2002
    Messages
    104
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 104
    Points : 128
    Points
    128
    Par défaut
    Bonjour,

    Pour éliminer le problème du Garbage Collector qui déplace le tableau, tu peux essayer d'utiliser la directive fixed : http://msdn.microsoft.com/fr-fr/library/f58wzh21.aspx

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2005
    Messages
    346
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2005
    Messages : 346
    Points : 119
    Points
    119
    Par défaut
    Pour éliminer le problème du Garbage Collector qui déplace le tableau, tu peux essayer d'utiliser la directive fixed : http://msdn.microsoft.com/fr-fr/library/f58wzh21.aspx
    J'ai essayé mais tel que le buffer est enregistré auprès de la fonction non managée, il ne s'agit pas d'un pointeur et fixed ne fonctionne qu'avec un pointeur...

    Voici l'enregistrement du buffer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    status = Imports.SetDataBuffers
                        (_handle, 
                        (Channel)i, 
                        minBuffers[i],
                        maxBuffers[i], 
                        (int)sampleCount);
    Et la déclaration de la fonction de ma DLL:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    [DllImport(_DRIVER_FILENAME, EntryPoint = "ps5000SetDataBuffers")]
            public static extern short SetDataBuffers(
                                short handle,
                                Channel channel,
                                short[] bufferMax,
                                short[] bufferMin,
                                long bufferLth);
    J'ai essayé de modifier short[] bufferMax et short[] bufferMin en type pointeur mais ça ne semble pas fonctionner ou alors, je m'y prends mal...

Discussions similaires

  1. Problème de synchronisation avec les tables
    Par rimy2mi dans le forum Hibernate
    Réponses: 0
    Dernier message: 11/11/2009, 10h14
  2. Problème de synchronisation avec attribut
    Par wizzy dans le forum Général Java
    Réponses: 1
    Dernier message: 22/02/2009, 23h01
  3. Problème de synchronisation avec Hibernate
    Par toutoune60 dans le forum JSF
    Réponses: 2
    Dernier message: 15/04/2007, 12h27
  4. Réponses: 13
    Dernier message: 20/03/2007, 17h04

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