Jump to content

ryank

NI
  • Posts

    10
  • Joined

  • Last visited

Posts posted by ryank

  1. But what do they do about closing them? Do they just rely on the automatic cleanup?

    One method I've used once (although I'm fairly sure I only used it in this example*) is to run my actual code in an asynchronous process (e.g. it would open the resource the first time and return it on request on subsequent runs) and monitor the execution state of the owning VI and clean up when the VI stopped. This worked for my example because it was working on a specific control, which was owned by a VI. It might work for an express VI, but it would require something like reference counting and garbage collection and probably wouldn't be worth it. For code which needs it, it's easier to just write the actual code with open and close outside the loop.

    * It's actually a cute example - it allows setting a custom blink color and speed for each control. I thought of augmenting it by adding the ability to smoothly pulse the control's color, since I have the code for that as well, but since I never used either of them in any actual code, I didn't bother. Today that might be better implemented in an XControl.

    I'm not sure of the exact mechanism, since I've never tried doing it using VI Scripting. In most cases when I write an Express VI, it's to create a reusable block of code that I can easily reconfigure, like this one, and not necessarily to make a hard concept easy to understand (which is what most of the built in ones are designed to do). Therefore, for my Express VIs, I'm okay with making the user call an init and a close if I'm managing resources (under the hood the init and close just operate on a functional global, and I can use a reference into the FGV to handle multiple sessions).

    For the SEH library, I did experiement for a while with allowing the user to call handler VIs for each error, either asynchronously or synchronously, but I took it out of the posted version because I was worried about the implications and because I intend to use this in RT systems, where arbitrarily spawning VIs to handle an error would be kind of a no-no smile.gif.

    That is a nice example, although I agree that it would make a good XControl.

  2. Don't know where the "attached discussion forum" is, but I've thought for years that "Elapsed Time" should be in ms resolution. It would have been useful then tongue.gif.

    Hehe, just to clarify, I'm not in R&D (not that there's anything wrong with being in R&D ;)) and I didn't write and don't maintain any of the core LabVIEW Express VIs. I'm referring specifically to the Express VIs linked above, which I did write. The forum I was referring to is linked from the document that contains the example. I won't post a direct link, because I know some forums frown on that.

    And for the record, I think the elapsed time VI accepts fractional numbers, so you can do ms resolution waits with it, you just have to divide by 1000 yourself :).

  3. Correct, but I was replying to Ryan's post, and presumably he wasn't refering to using your newly presented paradigm (or even something like Stephen's example from way back) in his past applications. I'm not actually sure that the SEH library would work as is for something like this. I haven't looked at it yet, but a quick glance at the article seems to indicate that it only supports specific actions, whereas I'm thinking of more complex code in addition to the standard error handling code. An OO local (or maybe even central) handler would work for that.

    Sorry, didn't mean to side-track things :). At one point I did have the ability to call a VI as one of the actions to take in the SEH, but I took it out because I didn't want to deal with all of the potential implications.

  4. Because Express VIs are a one-VI-operation, that VI needs to do everything related to its task. If that task involves writing and reading to a serial port, for instance, the VI would need to open the port and close it every single time it runs. Call it in a loop many times and this can become a performance issue.

    As Ryan said, this isn't something inherent to the technology, but it's what usually happens, and for good reasons.

    Like Gary, at times I've simply converted the VIs after their creation and removed the parts I didn't want. This is done by right clicking and selecting Open Front Panel.

    Also, I feel that part of the issue that people have with them is that many of the ones NI ships are geared towards mewbies and not towards experienced users. This results in you using an express VI and feeling your code to be "not code", since it looks too much like the NI demos where you string two blocks together and that's the end of the demo.

    By the way, NI used to have an express VI development toolkit, but it seems that this now ships as standard (at least with the Dev Suite I have). It's found somewhere in the Tools menu. It's something which could be useful if you want to script (or even just configure) some code using a wizard.

    There are some tricks they use to get around having to re-open resources every time (basically they use VI scripting to analyze whether the VI is being called in a loop), but they're very tricky and still have performance implications.

    You are correct that the Express VI Development Toolkit is now part of LV Core. I haven't checked, since I always install professional, but the original spec suggested that it might be in Base or Full as well, you definitely don't need Dev Suite. I believe the transition occured at 8.6, although it's possible it was 8.6.1.

  5. Sorry you couldn't make it sad.gif No, I haven't done any performance measurements on any of this code.

    Maybe I don't understand the issue, but the OO in NEC paradigm is specifically designed to meet that: you dynamic dispatch in the appropriate error handler on the fly.

    Oh - I see where the miscommunication is - yes, I presented on the error core, not error handling. I'd like to limit the conversations in this thread to the core, although we'll need to inevitable discuss handling too, but I'd like that to be in a separate thread (feel free to start one and link to it from here).

    Fair enough, although I do think you need to consider error handling when you think about the requirements of the core. For example, if you've got a good centralized handler and an easy way to get things to it, the core doesn't necessarily need the capability for multiple errors.

  6. The main problem I find with this approach is that sometimes you need to do something when handling the error (e.g. ask the user) in order to proceed with the process where the error occured. If the error handler is generic, this can become a problem, because the code for each process would be different (e.g. one might need to ask the user on a specific error, another might need to check an analog input and another might not need to do anything).

    That's why I differentiate between specific error handling, and central error handling. For my solution to specific error handling, and error categorization check this:

    http://zone.ni.com/devzone/cda/epd/p/id/6253

  7. Having attended the presentation I can certainly say that it was an excellent discussion and a very interesting topic. Several of us continued the conversation at dinner Thursday evening.

    The one aspect I wanted to say though is that whatever architecture gets chosen it should provide support for multiple errors. A good general purpose error handler should be able to see multiple error events and take the appropriate action. A prime example for this would be some system failure that is of a high priority and then a secondary error when trying to log the event. Both are certainly problems but how they are handled is completely different. With a single error the application would have to decide whether to ignore the error when logging the data or worse, override the more critical system error with the log error.

    Anyway, for those who were unable to attend I highly recommend reviewing the presentation.

    I go back and forth on this. While I'd love the ability to handle multiple errors, I'm also very concerned with performance (I do a lot of RT programming) and passing around an arbitrarily large object gets tough performance wise (not that the current string isn't already unbounded, but multiple errors would be aribtrarily larger :)). There are a couple of ways you could remedy this, one would be to store a table in memory and then pass around indexes to the table (i.e. pass by ref). Another, and the one I use currently, is just to use some sort of central error handler that recieves errors through a queue or FIFO. You still have to be diligent in invoking the message to the error handler before you overwrite the error or miss a subsequent one though.

    I presented at NI-Week 2009 on a couple of paradigms for extending the LabVIEW Error Handling Core (as inspired by all your posting here). Here are the resources from that presentation:

    Thanks for posting this, I unfortunately got dragged into a meeting and couldn't make the presentation, so I'm glad I at least got a chance to review the slides. One thing I'm curious about, have you done any type of comparison, performance wise, between some code implemented with this object based method and the same code with the traditional method? I've found its useful to try to characterize the performance of error handling both in terms of what it costs when there isn't an error and what it costs when there is one.

    Regards,

    Ryan K.

    NI Systems Engineer

  8. I agree. My main issue with them is typically they don't do quite what I want or don't give me quite the control I'm looking for.

    Can you explain this a bit? Is the init-destroy sequence executed each time during runtime or each time you drop an express vi on a block diagram?

    About Express VIs in general:

    There is nothing inherent in Express VIs that requires them to do an init/destroy sequence. However, Express VIs that work with open resources (i.e. the assistants) do have to have some way to open and close those resources, since there aren't explicit open and close operations as you'd get when using a lower level API. Therefore, it all depends on the Express VI, which is a good mantra to remember when thinking about Express VIs. At run time they're really not much different from a subVI, most of the gripes people have with them have to do with the way that certain Express VIs are implemented, not with the technology itself.

    About the Specific Error Handler:

    The nice thing about having one as a reference library is that its open source. If you don't like what it does, then change it :). Or better yet, post me a comment in the attached discussion forum so that I can make it what people want it to be :).

    The Specific Error Handler does not need any initialization or cleanup. Most of the processing of the error configuration is done when you hit OK from the configuration dialog, not at run time. At run time, it stores a fairly simple list of errrors and actions, the only performance hiccup will be that it does have to do a search in the event of an error. At the moment, I haven't done a whole lot to optimize the search, since I don't expect individual instances of the VI to have more than a dozen or so errors handled, but if anyone starts using larger lists in and individual instance, I'd be interested to know about it and I can consider doing some more optimization.

    Regards,

    Ryan K.

    NI Systems Engineer

    • Like 2
  9. QUOTE (jdunham @ May 27 2009, 08:22 PM)

    In our system, you can pass in a variant of whatever data wires you want and they are formatted into a string. However, by default this code, along with the code to grab the call chain, only runs if there is an error. There is no string handling unless there is an error thrown. Presumably if there is some kind of exception, need for real-time performance is probably over.

    All that stuff would be so much easier if it were supported internally by LabVIEW. It would be great for NI to show some leadership on this and modernize the error handling system. This would really boost my productivity. Hopefully at the very least they will attend the NI Week session

    I also suggest only doing the string manipulation in the event of an error. Actually, because of the nature of the specific error handling, I only do the string manipulation if there is an error that can't be handled locally and needs to be passed to the central error handler.

    However, I disagree that the need for run-time performance ends when an error is thrown. I think this represents a common misconception about errors: that once one happens, normal operation goes out the window. There are many "normal" errors that occur during the operation of most large systems. Timeouts are a prime example, but there are also lots of other examples (buffer overflows, underflows, the FTP toolkit's brilliant idea of throwing a warning after every operation, the timed loop error that is thrown every time you programmatically abort a loop). I find that particularly in real-time systems where we tend to have less complex messaging schemes, errors are often the method of choice for informing the caller of any unusual status as a result of their request (for example, reading from an uninitialized variable results in a warning that lets you know that the value might not be a valid data point yet). Most of these should be handled locally (ignored or retried) but some should be logged and/or reported (buffer overflow is a good example). I find that of the errors I commonly encounter, there are really only a very small number (out of memory, some problems with the filesystem, corrupt or missing OS or driver files, a code you've never seen before) that actually justify a system shutdown or the complete suspension of normal timing and operation.

    As for NI doing something about errors, I'll certainly post my specific error handler code as soon as I feel like it's ready, and Aristos Queue has already posted his embedded object error code. Eventually I suspect more tools will become part of the shipping product, but as this thread shows, it's far from a simple problem, especially since any new system absolutely has to support the overwhelmingly large number of VIs that rely on the error cluster.

    I'll certainly be at the session, and I imagine other NI folks will be as well.

  10. This is a topic I've been experimenting with for a while. Basically, I've found it's insufficient to have just a central error handler or just a local error handler. I think you need to have strategies for both. If you do just central error handling, it becomes difficult to do things like retry an operation, because it requires a lot of code for the central error handler to communicate with the specific section of code that threw the error. You also have to deal with the behavior of other code as you pass the error around, which is difficult, because different VIs and APIs treat incoming errors in different ways (which means that for any sufficiently complex secton of code, the behavior on an incoming error is essentially undefined). If you do just local error handling (I use the term "specific"), you end up calling dialogs or accessing files from loops you probably shouldn't be accessing them from (I do a lot of RT programming).

    My strategy has been to create a specific error handler which you call after each functional segment of code (which can be a loop iteration, subVI, or something more granular), and which can take actions based on specific error codes that happen in that segment (much like exception handling in other languages like Java). The specific error handler can take actions like retrying code, ignoring the error, converting it to a warning, or categorizing it. Ideally, the concept is that at the end of any functional segment of code, the errors from that segment have been handled if possible and categorized if not. You can then avoid passing them to other segments of code to get around the problem with undefined behavior that I mentioned before. For usability's sake, my specific error handler is an express VI that lets you configure a list of error codes or ranges and actions for each. I categorize errors by using the <append> tag in the source field, which keeps them fully compatible with all of the normal error handling functions (one drawback is that this requires string manipulation, which is kind of a no-no time-critical RT code, I haven't yet come up with an alternative I'm comfortable with though).

    A categorized error feeds into the central error handler (you can pass them with queues, events, FGs, or whatever you like), which can take actions based on categories of error. Each error category can take multiple actions, examples of actions are notifying the user, logging, placing outputs in a safe state, and system shutdown/reboot. Of course, there is always the case of an error code you've never seen before, which I usually treat as a critical error that puts the system in a safe state, logs, and notifies the user.

    At some point I'll get the kinks ironed out of my code to the point where I feel comfortable posting it (at that point it will probably show up as a reference design on ni.com), but I think the concepts are solid no matter what implementation you use.

    Regards,

    Ryan K.

    • Like 1
×
×
  • Create New...

Important Information

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