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.