Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Aborting analog input task doing async reads not working

Hello friends,

 

I have a class called AnalogInputFacade that is responsible for continuously reading in an async fashion from analog input. It begins reading from analog input when the Start() function on the AnalogInputFacade class is called and it should stop reading from analog input when the Stop() function on the AnalogInputFacade class is called. The class under discussion and it's base class are shown below:

internal abstract class NiTaskFacade
{
    protected Task NiTask;

    internal abstract void Start();

    internal abstract void Stop();

    internal IObservable<TaskDoneEventArgs> WhenTaskDone => Observable
        .FromEventPattern<TaskDoneEventHandler, TaskDoneEventArgs>(
            handler => NiTask.Done += handler,
            handler => NiTask.Done -= handler)
        .Select(x => x.EventArgs);

    internal IObservable<EveryNSamplesWrittenEventArgs> WhenNSamplesWritten => Observable
        .FromEventPattern<EveryNSamplesWrittenEventHandler, EveryNSamplesWrittenEventArgs>(
            handler => NiTask.EveryNSamplesWritten += handler,
            handler => NiTask.EveryNSamplesWritten -= handler)
        .Select(e => e.EventArgs);
}

internal class AnalogInputFacade : NiTaskFacade
{
    private static readonly Lazy<AnalogInputFacade> LazyInstance = new Lazy<AnalogInputFacade>(() => new AnalogInputFacade());
    private readonly AnalogMultiChannelReader _reader;
    private readonly Queue<double[,]> _readSamples = new Queue<double[,]>();

    internal static AnalogInputFacade Instance => LazyInstance.Value;

    private AnalogInputFacade()
    {
        NiTask = new Task("AnalogInputTask");
        var hardwareInfo = HardwareInfo.Instance;
        NiTask.AIChannels.CreateVoltageChannel(hardwareInfo.AnalogInputModuleName + "/ai0", "ai0", (AITerminalConfiguration)(-1), HardwareInfo.ChannelVoltageMinimum, HardwareInfo.ChannelVoltageMaximum, AIVoltageUnits.Volts);
        NiTask.AIChannels.CreateVoltageChannel(hardwareInfo.AnalogInputModuleName + "/ai1", "ai1", (AITerminalConfiguration)(-1), HardwareInfo.ChannelVoltageMinimum, HardwareInfo.ChannelVoltageMaximum, AIVoltageUnits.Volts);
        NiTask.Timing.ConfigureSampleClock("", HardwareInfo.AnalogInputSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.ContinuousSamples, 1000);
        NiTask.ConfigureLogging("C:\\tmp\\analogInput.tdms", TdmsLoggingOperation.OpenOrCreate, LoggingMode.LogAndRead, "Group Name");
        NiTask.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" + hardwareInfo.SecondDigitalIoModuleName + "/PFI0", DigitalEdgeStartTriggerEdge.Falling);
        NiTask.Control(TaskAction.Verify);
        _reader = new AnalogMultiChannelReader(NiTask.Stream);
    }

    internal override void Start()
    {
        _readSamples.Clear();
        NiTask.Start();
        _reader.BeginReadMultiSample(64, Callback, NiTask);
    }

    private void Callback(IAsyncResult ar)
    {
        double[,] readSamples;
        try
        {
            readSamples = _reader.EndReadMultiSample(ar);
        }
        catch (DaqException e)
        {
            Debug.WriteLine("Analog input read aborted.");
            Console.WriteLine(e);
            return;
        }
        
        _readSamples.Enqueue(readSamples);
        _reader.BeginReadMultiSample(64, Callback, NiTask);
    }

    internal override void Stop()
    {
        NiTask.Control(TaskAction.Abort);
        NiTask.Stop();
        NiTask.Control(TaskAction.Unreserve);
        Debug.WriteLine("Analog input task stopped.");
    }
}

Calling Start() for the first time works exactly as expected. Analog input is aquired properly & continuously. Calling Stop() is the problem. If I attempt to call Start() after calling Stop(), I get an error with the following exception:

NationalInstruments.DAQmx.DaqException
  HResult=0x80131501
  Message=Specified operation cannot be performed while the task is running.

Task Name: AnalogInputTask

Status Code: -200479

The task is not actually being stopped after the call to Stop(). I am aware that calling the stop function on a task does not terminate any pending read operations. The task will continue running until a timeout occurs or until all of it's pending operations complete. It is my understanding that calling NiTask.Control(TaskAction.Abort) should terminate any pending read operations on the task. However, this does not seem to actually be working.

 

I have found a workaround but, I do not like it because of the overhead it introduces. If I move the creation & configuring of the task to the beginning of the Start() function and call Dispose() on the task in the Stop() function, I am able to start & stop the analog input repeatedly without issue.

 

Am I doing something wrong here or is abort not doing it's job?

 

Thanks!

0 Kudos
Message 1 of 2
(1,887 Views)

Hi,


what happens if you invert this two lines to look something like this:

        NiTask.Stop();
NiTask.Control(TaskAction.Abort);

 

-Natalia 

Message 2 of 2
(1,852 Views)