LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

question about callbacks

I'm trying to design a small program that involves TCP socket reads and writes. In the help for the ConnectToTCPServer() function, there's a note about the callbackFunction:

 

The callback function should be short and should return as soon as possible.

 

My question is, does this statement apply principally to the ConnectToTCPServer() function, or to all callbacks? It seems that once I've called RunUserInterface(), pretty much all my processing will be within callbacks (or routines that the callbacks call).

 

Am I missing something here?

0 Kudos
Message 1 of 12
(4,078 Views)

To it's callback function.

Thanks.
CVI 2010
LabVIEW 2011 SP1
Vision Builder AI 2011 SP1
0 Kudos
Message 2 of 12
(4,055 Views)

Generally speaking, that warning applies to all callbacks: a control callback that takes too long to terminate blocks all user input on the user interface. One very common question on this forum is indeed "I have a callback that executes a test but I cannot stop it pressing a stop button because it is unresponsive!" CVI offers ProcessSystemEvents () function exactly to permit processing events in case of a long callback that blocks out other events, but it must be used with cautions: as you can read in the help for the function, Take care when using ProcessSystemEvents, because it can allow other callback functions to execute before it completes.


Additionally, there are several methods to execute code out of a control callback or without blocking the user interface:

  • UI timers
  • Asyncronous timers
  • Functions called via PostDeferredCall
  • Threads other than the main thread

In case of a long lasting procedure, I strongly encourage you to handle it in one of these methods instead of running it inside a control callback with embedded calls to ProcessSystemEvents () .



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
Message 3 of 12
(4,048 Views)

Interesting. This raises a different issue: will one callback block another?

 

I've constructed my program like this:

 

buttonCB:


{

    write a TCP message

    wait for newdataFlag

   process new data

}

 

TCPCB

{

    read TCP reply

    set newdataFlag

}

 

(newdataFlag is a global variable.)

 

Is there anything intrinisically wrong with this design? Will the fact that I'm in buttonCB prevent TCPCB from executing?

 

0 Kudos
Message 4 of 12
(4,045 Views)

OK, I did a bit of research, and it turns out that my concern is indeed the case. So, I've restructured the program like this:

 

buttonCB:


{

    write a TCP message

}

 

TCPCB

{

    read TCP reply

    process new data   

}

 

I'm not thrilled with it, because my TCP callback isn't as brief as I'd like it, but...it works. If I wished to improve on this, which of the options that Roberto recommended above would seem preferable in this application?

 

Thanks.

0 Kudos
Message 5 of 12
(4,035 Views)

I have little experience with TCP libary, but according to this page you must process messages in order to receive events in the callback; given this, your rewrite is on the right path. You could have inserted a ProcessSystemEvents inside your loop, but the change in logic is indeed better.

 

You could make your callback faster by moving processing out of it:

 

TCPCB

{

    read TCP reply

    PostDeferredCall (ProcessingRoutine, NULL);

}



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 6 of 12
(4,029 Views)

Hi, Roberto -

 

I tried the PostDeferredCall(), and it seems to work well. The documentation (ie, the online help) is a bit confusing, though. Am I correct in my understanding that this will not execute until ALL pending callbacks are finished, or merely the TCPCB that posted the deferred call?

0 Kudos
Message 7 of 12
(4,012 Views)

I am not sure about that. If pending events are lined up in a single queue that is processed when running function has finished, the deferred callback will be executed after already raised events but before others that may happend after PostDeferredCall. This may not be true if events have priority flag associated to them so that they may be processed in an order other than chronological one. I tend to consider the first option is the right one but I am not sure.

 

Additionally, consider that you may spawn an separate thread to process some events and launch the deferred function in that thread with ProstDeferredCallToThread (): this will definitely alter the order of event processing, especially with multicore PCs



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 8 of 12
(4,004 Views)

I'd like to pursue the issue of callbacks vs. deferred functions a bit more. My application has a "START" button. When the start button is pressed, it's callback sends a message through a socket to a connected device. Upon receiving this message, the connected device sends a block of data to the program (through the same socket). Once the program processes the data, it sends anotherh command for more data, and continues to do so until a "STOP" button is pressed.

 

I've tentatively designed my program like this:

 

ButtonCallback:

{

    set g_send to true

    send a "SEND" command to the device

}

 

TCPCallback:

{

    read the data from the socket 

    post a deferred call to process the data.

}

 

ProcessDataCallback:

{

    process the data, display, etc.

    if (g_send == TRUE)

        send another "SEND" command to the device.

}

 

(let's ignore for now how g_send is set to false)

 

If my understanding of how callbacks work is correct, TCPCallback and ProcessDataCallback will cause each other to cycle until g_send is set to FALSE.

 

From my very brief description above, can anyone see a flaw in this design? I welcome any input, but I'm particularly interested in whether a call could somehow be blocked, or fill up and eventually overrun the call stack.

 

Thank you for any input on this.

0 Kudos
Message 9 of 12
(3,996 Views)

I see no real flaw in this design: the deferred callback is fired by TCP callback after receiving a complete message and fires a new message to the device only after terminating handling data.

 

This structure stresses the system (intended as external device and PC application) to the maximum possible throughput, in the sense that each step is executed immediately after the preceding one is completed, without any pause or delay.

 



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 10 of 12
(3,969 Views)