Jump to content

To Callback Or Not To Callback


Recommended Posts

I have noted with interest Jim Kring's referral to usding callbacks in his code on several different topics. I have used callbacks (I think) with LV occurrences to signal arrival of hardware messages in IO queues and for DLL's written in C communicating with the SCSI bus. However I am not convinced that callbacks are always a good solution. I once had an interesting discussion (read argument) with a "programmer" <see rant> who suggested solving a problem via a callback simply because the operation could take a long, indeterminate period of time (in actual fact this time was only 1-2 seconds!). I argued that in LabVIEW, create a separate fibre (ie a "loop" within a thread :) ) and just wait for the process to complete!

Having recently been exposed to the Teststand GUI that is written in ActiveX with callbacks linked to buttons :angry: I think the callback can obfuscate the code especially from an understanding point of view. The only reason I can think for a callback is the freeing up of the current process so that the user can "abort" and the code is not "locked" inside a DLL/process/function node. Are there others?

Given LV lends itself to dataflow and IMHO callbacks "break" that dataflow paradigm, what are the advantages of callbacks? Perhaps someone can point out when and where they should be used or discouraged. And more importantanly perhaps add some pointers on creating/using callbacks in LV.

cheers, Alex.

<rant>I could have throttled that programmer as I think he was ultimately responsible for us not getting the project. I use the term programmer loosely because a university student in physics should not be advising companies on how to build professional, maintainable, code. If he'd at least studied com. sci. or prog. eng. as an undergraduate I could have yeilded to the argument. But to not know LabVIEW, been programming for less than 6 months, and believe that "callbacks" were the answer to a database query poblem is just ... grrrrr .... Guess I am learning that being right does not mean successful.</rant>

Link to comment

I'll take a quick stab at this...

I like to use the callback pattern for asyncronous event handling, especially when you may need to spawn multiple instances of the handler. The beauty of the callback is that the user who creates and registers the callback does not need to have any awareness of the underlying framework that listens for the event and spawns/manages the callbacks. The user can simple pass a callback VI reference into the framework to register it as the event handler. If you want a good example, take a look at the TCP Server example that I have posted on OpenG. This example allows you to register a VI to recieve TCP connection references when a client connects to a TCP server that is listening on a specified port. In this example, the TCP Server framework manages the TCP Listener process(es) and the spawing of connection handlers. It also provides a usefull status info VI to get information on the number of clients that are connected (to multiple instances of the connection handler that are running asyncronously).

Sure, callbacks "break the dataflow paradigm" but dataflow isn't the answer to everything in all instances. If you limit yourself to a set of strictly defined wire routes then you cannot possible handle N(any number of) asyncrounous threads. Why limit yourself..?

Link to comment

From the web: callback - A scheme used in event-driven programs where the program registers a subroutine (a "callback handler") to handle a certain event. The program does not call the handler directly but when the event occurs, the run-time system calls the handler, usually passing it arguments to describe the event.

Okay, so that means that a callback is really registration of a link to a handler with a system/process? Is there more to it than that? From your server example it would seem that the server is the main vi (run-time system) and the that callback handler is the "handler" vi? But in this case there is not registration as such as the server contains both the registration and the system to handle the registration. Have I got that right?

IOW in your TCPIP server example the server would seem to be both the engine and the register-er of the callback? Correct or am I just being plain dumb ;)

Link to comment

Yes, the TCP Server example both (1) creates the event listener (generator) and (2) provides the ability to register the event callback (handler) VI. Perhaps it would make sense to seperate these two things into some more general utilities. However, in this case the TCP Server only required a single callback VI per event source (one connection handler, per new connection) so I didn't need anything fancy in terms of managing the registration -- I simply stored the call-back RefNum in the TCP Server GOOP data store.

Link to comment
  • 2 weeks later...

Callbacks in LabVIEW itself are, although possible since 7.0, indeed an anachronisme. But there are situations where it would probably make sense to use them.

Callbacks in low level drivers are an entirely different issue. They are one way to allow an application to use asynchronous operations in a way without having to rely on interrupts or such things, which in modern OSes are out of reach of user applications anyhow. For cooperative multitasking systems this is basically the only way to do asynchronous operations without directly using interrupts or loading the CPU with lots of polling.

Another possibility to handle asynchronous operations on multtasking/multithreading systems is to use events. LabVIEW occurrences are in fact just that. Eventhough LabVIEW wasn't a from begin on a real multithreading system, for the purpose of its internal diagram scheduling it came as close as it could get to real multithreading.

Asynchronous operations are indeed inherently more difficult to understand and handle correctly in most cases. Especially in LabVIEWs dataflow world they seem to sometimes mess up the clear and proper architecture of a dataflow driven system. But they can make a big difference between a slow and sluggish execution where each operation has to wait for the previous to finish and a fast system where multiple things seem to happen simultanously while a driver waits for data to arrive.

With the more an more inherent real multithreading in LabVIEW this has become less important but in my view it is a very good and efficient idea to use asynchronous operations of low level drivers if they are avaialalbe. They way I usually end up doing that in the past is translating the low level callback or system event into a LabVIEW occurrence in the intermediate CIN or shared library. Of course such VI drivers are not always very simple to use and synchronous operations should be provided for the not so demanding average user. They can even be based on the low level asynchronous interface functions if done right.

But as long as you stay on LabVIEW diagram level only, callback approaches seem to me in most cases a complication of the design which is not necessary. As you have properly pointed out, having a separate loop in a LabVIEW diagram handling such long lasting operations is almost always enough.

That is not to say that Jims solution is bad. He is in fact using this feature not strictly as a callback but more like a startup of seperate deamons for the multiple instances of the same task, a technique very common in the Unix world. In that respect it is a very neat solution of a problem not easily solvable in other ways in LabVIEW.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.