05-12-2014 09:04 AM
I have an application issue that I need a bit of help with 🙂
I am reading a lot of data - roughly 1msps, and things are fine when testing on hardware without stressing the application. However, when my process is running for real then there is so much going on that I sometimes miss a bit of data - which is NOT a problem for me.
The error is basically:
NationalInstruments.DAQmx.DaqException: Attempted to read samples that are no longer available. The requested sample was previously available, but has since been overwritten.
Now, there seems to be some sort of memory leak when this occurs, and after a short while of real running then I end up with out of memory exceptions:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at NationalInstruments.AnalogWaveform`1.GetRawData()
at Strecon.Drivers.NI.NI9223.AnalogInCallback(IAsyncResult ar)
Is there some special cleanup calls that I can insert into my application (analog callback below)
try
{
if(myTask != null && myTask == ar.AsyncState)
{
// Read data from channel
NationalInstruments.AnalogWaveform<double> data;
data = analogInReader.EndReadWaveform(ar);
// Check for and report any overloaded channels
// Store data
//RawData.Enqueue(data);
double[] rawdata = data.GetRawData();
vdaStrainDataValues.SetValue(rawdata, DateTime.Now);
// Continue sampling
analogInReader.BeginMemoryOptimizedReadWaveform(samplesPrFrame, analogCallback, myTask, data);
}
}
catch(Exception ex)
{
log.Warn("Exception in callback", ex);
ModuleStop(); //My stop start stuff
ResponseObject ro = ModuleStart();
}
Btw. I am on 32 bit (I have one external HW driver that is not available as 64bit) and NI-DAQmx is 9.7.0f0
I am not 100% sure that there is something wrong with NI-DAQmx, but it is certainly where it manifests itself in my app 🙂
Help / suggestions is greatly appreciated.
05-13-2014 03:29 AM - edited 05-13-2014 03:30 AM
Hi Larover88
First let me explain the error you get. So when you start you data acquisition with X number of samples to read per Y number of seconds then there is allocated a buffer to keep your data values. If you wait long enough with reading out the data values there is not enough room in the buffer to store all the values and you get a buffer overflow. In this case it is shown because you try to read some values that is deleted due to the overflow.
My best recommendation is to keep your data acquisition in a seperate thread in your application and make sure you don't do anything else in that thread.
You should be able to run you DAQ application at a fairly equal loop rate, if you put analysis and maybe also file i/o into this thread there will be a lot of factors that can make the loop slow down and give you a buffer overflow.
So I would do the following:
Main program:
StartDAQThread();
StartAnalysisLogThread();
While(Stop == false) {
}
SignalStopToThreads();
WaitOnThreadsToComplete();
StartDAQThraed:
Loop with 100hz {
Read array of values from DAQ
Store array of values in a Queue
}
StartAnalysisLogThread:
While{
if (no values in queue)
Wait for new values in queue
else (values in queue)
Read out values from queue
Process values i.e. with FFT
Log Results
}
The sole purpose of this is to move the buffered values from the small memory on the actual DAQ device and into the large memory we have on the PC. To not get errors we need to have a fairly constant rate when reading the DAQ, and to get this we isolate the DAQ tasks in a single thread. If the AnalysisLogThread is slow sometimes the memory will just build up on the PC but that is no problem (unless it is always too slow to process the data coming in).
This structure is called Producer Consumer structure. It is a design pattern you see in both C++, C#, LabVIEW, Java and many other programming languages. Meaning if you want some inspiration and examples for doing this online just google "producer consumer <<insert programming language>>".
Best Regards
Anders Rohde
Applications Engineer
National Instruments Denmark
05-20-2014 04:04 AM
Hi,
Is there an actual c# or vb.net example of this process using a simple DAQMx analogue multi channel read?
It would be very helpful.
Regards
Steve
05-20-2014 04:10 AM
Thank you for the reply Anders.
It is actually already running in a separate thread, however there is no guarantee in .NET that the thread will get CPU time.
When it (the exception) occurs (and it always will at some point in time in .NET) then I saw some some memory not beeing released, and I suspected (and still do) that there is a memory leak somewhere in the NIDAQ framework that is triggered by this exception.
I reduced the problem by using two threads, one for sampling and one for processing, and then a lot of data copying.
I propose that you increase your input sample buffers to having n arrays for sample data instead of just one - circular buffer of arrays. Then I could allocate say 50 arrays of ½megabyte size and just follow the sample pointer in a separate thread. I don't care about the potential lag since this can be adressed in software...
Kind regards.