From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Digital I/O

cancel
Showing results for 
Search instead for 
Did you mean: 

Terminating a C# application that uses asynchronous reading (PCI-6518, DAQmx 7.1.0.388, VS C# 2003)

Hi.

I'm developing an application using the PCI-6518 Digital I/O board under Visual C# 2003 with DAQmx V. 7.1.0.388. Everything is working fine so far, except one last open point:

If I terminate my program, the application hangs (mostly, from time to time it terminates properly) in a way, that I can't even kill it using the TaskManager. All I can do is to reboot the machine. Maybe someone can help me here. The problem occurs only when using asynchronous read access.

Some code snippets:

This is the method I use to register my callback functions that are called with the incoming data if a change was detected. It uses the helper method below to create a new Reader and starts immediately listening for incoming data.

        public bool ActivateAsyncByteReadPort(int port, AsyncByteReadCallback callback)
        {           
            if(IsInputChannel(port)){
                DigitalSingleChannelReader daqReader=CreateAsyncReader(port);
                m_ReadPorts[port]=daqReader;
                m_ByteReadCallbacks[port]=callback;
                daqReader.BeginReadSingleSamplePortByte(new AsyncCallback(OnDataReady),port);                                  
                return true;               
            }                       
                                                       
            return false;
        }

        private DigitalSingleChannelReader CreateAsyncReader(int port)
        {
            if(m_ByteReadCallbacks[port]==null)
            {
                string lineString=m_strDeviceId+"/port"+port;
                Task digitalReadTask = new Task(null);
                m_Tasks.Add(digitalReadTask);
                digitalReadTask.DIChannels.CreateChannel(lineString,"",ChannelLineGrouping.OneChannelForAllLines);
                digitalReadTask.Timing.ConfigureChangeDetection(lineString,
                                                                                                    lineString,
                                                                                                    SampleQuantityMode.HardwareTimedSinglePoint);
                //disable timeout, wait forever for incoming data because the PLC may not be active yet
                digitalReadTask.Stream.Timeout=-1;                               
                DigitalSingleChannelReader daqReader = new DigitalSingleChannelReader(digitalReadTask.Stream);                                                
                m_ReadPorts[port]=daqReader;
                return daqReader;
            }
           
            return (DigitalSingleChannelReader)(m_ReadPorts[port]);
        }

This method is called every time a change was detected:

        private void OnDataReady(IAsyncResult result)
        {
            int port = (int)(result.AsyncState);           
            byte data = ((DigitalSingleChannelReader)m_ReadPorts[port]).EndReadSingleSamplePortByte(result);                   
          
            if(m_ByteReadCallbacks[port]!=null)
                ((AsyncByteReadCallback)(m_ByteReadCallbacks[port]))(data);
        
            ((DigitalSingleChannelReader)m_ReadPorts[port]).BeginReadSingleSamplePortByte(new AsyncCallback(OnDataReady), port);           
        }

As I already said, this works fine and does what it is supposed to do (it calls the callbacks when input changes). However, if I want to terminate the application, it seems that OnDataReady (or more likely the BeginReadSamplePort) doesn't stop. I tried the following (without success):

        public bool Close(){

                foreach(Task task in m_Tasks)
                {
                    task.Control(TaskAction.Abort);       
                    task.Dispose();                   
                }
                m_Device.Dispose();                       
          
            return true;
        }

So my question: What's the proper NI-way to terminate this application? How can I interrupt the BeginReadSingleSamplePortByte calls?

Thanks & yours,
Dominik
0 Kudos
Message 1 of 5
(5,092 Views)
Hi again.
Small update: I've got the same problem with the 8.5 version of the driver. Any ideas?

Yours,
Dominik
0 Kudos
Message 2 of 5
(5,030 Views)
Hello Dominik,

could you please try different values for digitalReadTask.Stream.Timeout and see if the behaviour changes when you terminate the application?

Thank you,
Johannes
0 Kudos
Message 3 of 5
(5,004 Views)
Hi,

Try issuing a device reset from the Measurement and Explorer Tool.  If this works, then (as an unclean solution), you can create a separate application to call DAQmxDeviceReset or call DAQmxDeviceReset before terminating your application from another thread.

Jeff



@DRau wrote:
Hi.

I'm developing an application using the PCI-6518 Digital I/O board under Visual C# 2003 with DAQmx V. 7.1.0.388. Everything is working fine so far, except one last open point:

If I terminate my program, the application hangs (mostly, from time to time it terminates properly) in a way, that I can't even kill it using the TaskManager. All I can do is to reboot the machine. Maybe someone can help me here. The problem occurs only when using asynchronous read access.

Some code snippets:

This is the method I use to register my callback functions that are called with the incoming data if a change was detected. It uses the helper method below to create a new Reader and starts immediately listening for incoming data.

        public bool ActivateAsyncByteReadPort(int port, AsyncByteReadCallback callback)
        {           
            if(IsInputChannel(port)){
                DigitalSingleChannelReader daqReader=CreateAsyncReader(port);
                m_ReadPorts[port]=daqReader;
                m_ByteReadCallbacks[port]=callback;
                daqReader.BeginReadSingleSamplePortByte(new AsyncCallback(OnDataReady),port);                                  
                return true;               
            }                       
                                                       
            return false;
        }

        private DigitalSingleChannelReader CreateAsyncReader(int port)
        {
            if(m_ByteReadCallbacks[port]==null)
            {
                string lineString=m_strDeviceId+"/port"+port;
                Task digitalReadTask = new Task(null);
                m_Tasks.Add(digitalReadTask);
                digitalReadTask.DIChannels.CreateChannel(lineString,"",ChannelLineGrouping.OneChannelForAllLines);
                digitalReadTask.Timing.ConfigureChangeDetection(lineString,
                                                                                                    lineString,
                                                                                                    SampleQuantityMode.HardwareTimedSinglePoint);
                //disable timeout, wait forever for incoming data because the PLC may not be active yet
                digitalReadTask.Stream.Timeout=-1;                               
                DigitalSingleChannelReader daqReader = new DigitalSingleChannelReader(digitalReadTask.Stream);                                                
                m_ReadPorts[port]=daqReader;
                return daqReader;
            }
           
            return (DigitalSingleChannelReader)(m_ReadPorts[port]);
        }

This method is called every time a change was detected:

        private void OnDataReady(IAsyncResult result)
        {
            int port = (int)(result.AsyncState);           
            byte data = ((DigitalSingleChannelReader)m_ReadPorts[port]).EndReadSingleSamplePortByte(result);                   
          
            if(m_ByteReadCallbacks[port]!=null)
                ((AsyncByteReadCallback)(m_ByteReadCallbacks[port]))(data);
        
            ((DigitalSingleChannelReader)m_ReadPorts[port]).BeginReadSingleSamplePortByte(new AsyncCallback(OnDataReady), port);           
        }

As I already said, this works fine and does what it is supposed to do (it calls the callbacks when input changes). However, if I want to terminate the application, it seems that OnDataReady (or more likely the BeginReadSamplePort) doesn't stop. I tried the following (without success):

        public bool Close(){

                foreach(Task task in m_Tasks)
                {
                    task.Control(TaskAction.Abort);       
                    task.Dispose();                   
                }
                m_Device.Dispose();                       
          
            return true;
        }

So my question: What's the proper NI-way to terminate this application? How can I interrupt the BeginReadSingleSamplePortByte calls?

Thanks & yours,
Dominik



0 Kudos
Message 4 of 5
(4,992 Views)

This problem is caused by a pending asynchronous read/write operation with an infinite timeout.  You can reset he device programatically as a workaround to terminate the async operation:

 

NationalInstruments.DAQmx.DaqSystem.Local.LoadDevice("dev1").Reset();

 where "dev1" is the name of your device.  NI should really provide a method to terminate async operations, other than timeout.

0 Kudos
Message 5 of 5
(3,212 Views)