12-01-2015 07:48 AM
public List<byte> ReadData(int bytesToRead) { int digitalSampleCount = CalculateNumberOfSamplesNeededFromByteCount(bytesToRead) + 1; List<DigitalState> clockStates = GenerateClock(digitalSampleCount); DigitalWaveform clockWaveform = CopyStatesIntoWaveform(clockStates); using (NationalInstruments.DAQmx.Task writeClockTask= new NationalInstruments.DAQmx.Task("Clock Writer")) { writeClockTask.DOChannels.CreateChannel(clockLine, "Clock Line", ChannelLineGrouping.OneChannelForEachLine); writeClockTask.Timing.ConfigureSampleClock("", 20000, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, digitalSampleCount); DigitalSingleChannelWriter clockWriter = new DigitalSingleChannelWriter(writeClockTask.Stream); using (NationalInstruments.DAQmx.Task readDataTask = new NationalInstruments.DAQmx.Task("Data Reader")) { readDataTask.DIChannels.CreateChannel(dataLine, "Data Line", ChannelLineGrouping.OneChannelForEachLine); readDataTask.Timing.ConfigureSampleClock("/PXI1Slot6/PFI5", 20000, SampleClockActiveEdge.Falling, SampleQuantityMode.FiniteSamples, 16); var dataReader = new DigitalSingleChannelReader(readDataTask.Stream); var result = dataReader.BeginReadWaveform(16, new AsyncCallback(ReadTaskCallback), readDataTask); readDataTask.Start(); // ***** This line throws exception the second time ReadData(int) is called **** clockWriter.BeginWriteWaveform(true, clockWaveform, new AsyncCallback(WriteClockCallback), writeClockTask); writeClockTask.WaitUntilDone(); readDataTask.WaitUntilDone(); DigitalWaveform readData = dataReader.EndReadWaveform(result); Console.WriteLine("Number of samples read: {0}", readData.Signals[0].States.Count); for (int i = 0; i < readData.Signals[0].States.Count; i++) { Console.WriteLine("State at {0}: {1}", i, readData.Signals[0].States[i].ToString()); } } } return new List<byte>(); }
I have the above method, which creates 2 tasks. One to write a clock signal out, one to read data back in. Everything works great the first time the function is called.
HOWEVER, the "readDataTask.Start()" throws a DaqException, claiming "Specified operation cannot be performed while the task is running". Maybe I don't have a firm grasp on C# and "using", but shouldn't "readDataTask" get cleaned up when the using block falls out of scope? And shouldn't new-ing up a new task actually create a new task?
12-01-2015 08:43 AM
Looks like there's something under the covers that isn't being cleaned up when it should be. If I run the method twice, with 4 seconds between each call, the exception gets thrown. But if the method is run 60 seconds apart, no exception....
12-01-2015 09:58 AM
A little more digging: It appears that there are 3 Worker threads that get spun up by the above function, and one has to wait for those 3 Worker threads to exit before that function can run again.
In addition, the problem only arises when using an external sample clock on the read data task. Use the default clock and everything works good. This is code that exhibits the problem. The key difference between this code and the above code is the "readDataTask" uses different clock sources. The below code uses the default clock. The above code uses "/PXI1Slot6/PFI5" for the sample clock (I have a signal generator hooked up to PFI5 to drive the clock).
public void ReadSomething() { DigitalWaveform clock = new DigitalWaveform(20, 1); for(int i=0; i<20; i++) { if (i % 2 == 0) clock.Signals[0].States[i] = DigitalState.ForceDown; else clock.Signals[0].States[i] = DigitalState.ForceUp; } using (NationalInstruments.DAQmx.Task writeDataTask = new NationalInstruments.DAQmx.Task()) { writeDataTask.DOChannels.CreateChannel(clockLine, "", ChannelLineGrouping.OneChannelForEachLine); writeDataTask.Timing.ConfigureSampleClock("", 10000, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, 20); var clockWriter = new DigitalSingleChannelWriter(writeDataTask.Stream); using (NationalInstruments.DAQmx.Task readDataTask = new NationalInstruments.DAQmx.Task()) { readDataTask.DIChannels.CreateChannel(dataLine, "Data Line", ChannelLineGrouping.OneChannelForEachLine); readDataTask.Timing.ConfigureSampleClock("", 10000, /****** USES DEFAULT CLOCK!!!! ******/ SampleClockActiveEdge.Falling, SampleQuantityMode.FiniteSamples, 5); var dataReader = new DigitalSingleChannelReader(readDataTask.Stream); var result = dataReader.BeginReadWaveform(5, new AsyncCallback(ReadTaskCallback), readDataTask); readDataTask.Start(); clockWriter.BeginWriteWaveform(true, clock, new AsyncCallback(WriteClockCallback), writeDataTask); readDataTask.WaitUntilDone(); writeDataTask.WaitUntilDone(); var d = dataReader.EndReadWaveform(result); } } }
12-01-2015 01:22 PM
Figured it out.....
One has to start the task BEFORE starting the read.
This will cause problems.
public void ReadSomething() { /*Snip setup code*/ using (NationalInstruments.DAQmx.Task readDataTask = new NationalInstruments.DAQmx.Task()) { /*Snip setup code*/ var result = dataReader.BeginReadWaveform(5, new AsyncCallback(ReadTaskCallback), readDataTask); readDataTask.Start(); } } }
This works flawlesssly
public void ReadSomething() { /*Snip setup code*/ using (NationalInstruments.DAQmx.Task readDataTask = new NationalInstruments.DAQmx.Task()) { /*Snip setup code*/ readDataTask.Start(); var result = dataReader.BeginReadWaveform(5, new AsyncCallback(ReadTaskCallback), readDataTask); } } }
Note that "readDataTask.Start()" is called BEFORE "BeginReadWaveform" in the working code.....
Is this covered in the documentation somewhere?