-
Posts
1,068 -
Joined
-
Last visited
-
Days Won
48
Content Type
Profiles
Forums
Downloads
Gallery
Everything posted by mje
-
Wonder if IPB has an android one in the works?
-
The ability to force reentrant VIs inline is nice too. Make all those pesky accessor VIs quicker in tight loops.
-
Oh boy, been wanting these two for ages: New Cluster Constant After defining the elements in a cluster constant, right-click on it to replace it with a small icon on your block diagram to clear up space and improve code readability. Save VIs Without Compiled Code Simplify source code management by separating the compiled objects from the actual LabVIEW source code. Can I get a hellyeah? The new merge error node is pretty awesome too. I think this is my favorite NI week since the introduction of Objects. Also very curious about the Network Streams API, but there seems to be a few 404s on that page...
-
Ok, here's what I got. You may be aware I have a messaging architecture I've been using for a bit now, MessagePump. It has proven to be very robust to me over the last two years, and I've been wanting to "fix" it a bit by updating it and making it part of a more comprehensive library. Ultimately, the idea of an event is now almost gone from my framework, and replaced with Messaging. Fundamentally they're the same: some arbitrary signal which is broadcast to a queue owned by some other task. As I buried down into the design of an event based system, I found myself running into much of the same situations I did when designing the messaging framework, and I really didn't like how similar they were going to end up being. So I think I've decided to expand on the existing system and add a few extra classes, and ultimately forget about starting a new type of architecture. Here's where I've landed: Note that NONE of this beyond the existing MessagePump class has been implemented, and even that class is going to change when I get around to making version 2.0 as there were a few decisions I made on it that I'm not particularly happy with, and the class really ought to be redesigned now that DVRs exist. The whole idea of registering as an event observer is gone (as are events). Instead, messages will be passed around continuously, a given View is free to implement whatever message handler it wants. By design a MessagePump can take any message, ones it does not implement handlers for are ultimately discarded harmlessly by the MessagePump base class. When a View wishes to broadcast a message, it must decide if it wants to contain the scope of the message to itself and it's children, or if it wants the message to be global. In the former case it posts the message to itself, in the later case the View obtains a reference to the owning Application and broadcasts it from there. Synchronous messaging, if needed, can be performed a number of ways by the existing MessagePump framework, no changes needed there. There will be limitations though. The idea of "bubble" events won't work without some extra work. The bubbling system requires the signal to work it's way up the hierarchy, from source, to parent, to grandparent. The system I've described works in reverse, things naturally flow down from source, to child, to grandchild.
-
Yes, this is exactly what I'm shooting for. I'm mostly modeling the behavior after the Document/View architecture I used in my old C++/MFC programming days. Indeed, I've also learned that mistake. By setting the UI state immediately in response to an event triggered in the UI means that the view is keeping some amount of state information. This is a no-no, as unless one is really careful, synchronization issues can go unnoticed and be a generous source of buggy behavior. Basically I'm going to have an Application class which exposes a public API for all views to use. When a view needs to start a test, it fires Application:StartTest(), which in turn will signal an Application:TestStartedEvent. It is the responsibility of any View classes to subscribe to the TestStartedEvent if they need to change their UI in response to this state change. During that response they can query the Application class as necessary for data to update the UI. Agreed, which is why my class hierarchy is panning out to be somewhat different from the one you attached: I think that's not so much a problem of the chosen architecture, but what is ultimately used as an "event". If an out of the box, LV User Event is used, no, it won't. But if I roll my own it can easily be implemented. Yes, but of course ViewB and ViewA are not related except by virtue of having a common ancestor. I'm wrestling with how I want the event manager to act, I'm exploring a few different directions here. I'll post more when I've thought at least one of them out more thoroughly. One sticking point I've run into in my design is that I have to allow for multiple instances of a given View. I had a good solution but it relied on singetons, but I think I can adapt it...more later, hopefully before NI Week. No, you got it. But I think I've changed my mind. Events aren't really the way to go in that situation: If all views are required to respond an event, this is better implemented via an abstract class method of the View class, not an event. Since it's a method, it is by definition synchronous. Similarly, if an event can be, but is not required to be overriden a simiple overridable method will do the trick. Argh, I somehow hit the submit button by mistake, please bear with me as I rush to finish the post...there doesn't seem to be a delete option? Anyways, your CoC idea is interesting as well. I've been wrestling with how to deal with errors in background processes that run asynchronously. I...don't have a solution yet.
-
It might be. I remember the example you posted a year (?) ago, but I didn't have the time to wade through it determine how to implement it into my existing framework. As you said, adding commands did some somewhat involved. I'd love to see a current version of it, if for any reason even just an academic curiosity. But please, don't rush it if it's not already on the burner. Indeed! I was using it basically in the context of the observer pattern previously mentioned. It's tough to say. The architecture is still rather nebulous in my brain. I definitely am going with some kind of application object which maintains ownership of data, and allows an arbitrary amount of views which interact with the app. Views would be loaded dynamically, and could also be defined outside the scope of the core application (plug-ins). It's the exact means of interaction that I'm still deciding. Simple API via exposed class methods? A messaging system? Combination of the two? Something else entirely? Synchronous "events" creep in to one way I was thinking of designing my UI. I like the idea of bubble style events for some features. Say the App object owns ViewA, which in turn owns ViewB. Now ViewB generates an event, it would bubble up to ViewA. If ViewA handles the event, everything ends there, however ViewA decides it has not handled the event, or if ViewA doesn't implement the event observer at all, the event bubbles up to the Application. Note this implies that these types of events return a value. A system like this demands synchronicity because whatever means of signaling is implemented, the code must block at each observer to determine if that node is the end of the event chain. Situations like that though can also open an application to deadlock though, I'm not sure if I want to go there. I don't know if I want to implement this type of event system though. I was more curious if there was any way to make LabVIEW events even compatible with a synchronous model rather than rolling my own using various combination of sync objects.
-
Me too in most cases. Yep, you've pretty much got it. Like I said, basic standard stuff. Just nothing that works out of the box, so to speak, in LabVIEW. Naw, there's definitely cases where synchronous events are used. You don't even need to look outside of LabVIEW. Don't have LV handy at the moment, but I think NI calls them filter events? Stuff like the Panel Close? event, which allows you to discard it. This event is by definition synchronous, since whatever signals the event must block until the event frame finishes executing to know whether or not to discard the event and proceed with the follow up event. I've also worked with similar events in other UI environments with in bubble style events, where an event is generated by an object, and bubbles up to each containing object until either everything has serially had their turn or the event gets discarded. Also done plenty of these style events other languages where the event delegates are pretty much just function pointers. Events are signaled by rolling through the pointer array serially (for synchronous cases). Sure, I've done some C#, but more C/C++. I've been around enough programming languages where I see them all as just grammar (even LabVIEW). They get a job done, you just need to know how to use each. There are valid use cases for both style of events, and what should be used really just depends on the behavior you want to design around. I just never was aware of an "out of the box" way to do the synchronous calls in LabVIEW. Norm! That's awesome. I remember seeing a discussion about that a while ago but completely missed the sync/async part of the topic, thanks for jogging my memory. I'll have to check that out first thing when I get in to the office on Monday. I worry though that since the behavior change from asynchronous to synchronous isn't documented, that it might be a bug and I'm not sure I'd be comfortable releasing code which requires that behavior. Still warrants further investigation though. Funny you also play with the notifier. That's one of the ways I was thinking of being able to return a value from the events.
-
I'm starting to plan out the architecture for an application I'm going to have to write by the end of the year and really want to be able to use some kind of object based event system for synchronization. Basically ObjectA will have a whole slew of events, and other objects are free to subscribe and unsubscribe to public ones as they see fit. Standard stuff. The rub being that some events need to be synchronous: the code which invokes the event must block until all subscribers have returned. Now correct me if I'm wrong, but this excludes the ability to use the built in user events without getting creative. For static events, ones generated by say, the user interface, you can check a box when configuring an event structure case to lock the front panel until event is processed, which essentially makes that particular event frame* synchronous: the action which invoked the event won't return until the event has been processed. For user events, this option isn't available, they appear to be entirely asynchronous. Now I have a few ideas brewing in my head, some more mature than others, and I think it can be implemented abstractly enough that the resulting framework can be reasonably light weight and extensible. I'm just wondering if anyone is aware of existing LabVIEW frameworks that do this? I don't need anything fancy like inter-process/remote communication, although recent discussions have really got me thinking about it, seems like it could be a fun challenge to add that layer into the mix. *Aside: Something I haven't characterized well, but I find fascinating: if you have multiple event structures pending on the same static event, LabVIEW appears to be able to sort out the fact that each individual frame might or might not be synchronous. I find the idea that synchronicity is strictly a property of the delegate and not the event itself interesting. Cheers, -m
-
I'll be there as well! Arriving Monday, staying at the Hilton. Pretty much attending everything including the BBQ, though Monday night is up in the air (we're not an alliance member).
-
Anyone know how much time to allow for travel from the convention center to the airport? How's pre-rush hour traffic? I'm worried I might have to bust out of the last 2:15 thursday session so I can grab my bags and make a 5:15 flight... For the record, my list: State Machine versus State Machine - Tue 10:30 AM From Prototypes to Products - Building Commercial Instruments with LabVIEW Tue 1:00 PM LabVIEW Graphical Scripting - Tue 2:15 PM LabVIEW Compiler Under the Hood - Understanding the Optimizations in 2010 Tue 3:30 PM LabVIEW UI Tips and Tricks - Tue 4:45 PM LabVIEW Design Patterns and SMoReS - Wed 10:30 AM What's New in NI LabVIEW - Wed 1:00 PM Development and Deployment of Large LabVIEW Applications - Wed 2:15 PM Best Practices for Memory Management and LabVIEW Code Optimization - Wed 3:30 PM LabVIEW GUI Design 2.0 - Wed 4:45 PM LabVIEW Classes: The State of the Art - Thu 10:30 AM LabVIEW Coding Challenge Finals - Thu 12:00 PM LabVIEW Object-Oriented Programming Design Patterns for Large Systems - Thu 1:00 PM Beyond the Basics: LabVIEW Debugging Techniques - Thu 2:15 PM Also, events which I really want to attend but can't due to conflicts. Hardware Abstraction Layers Using LabVIEW Object-Oriented Programming - Thu 10:30 AM New Features and Best Practices for Network Data Transfer - Thu 1:00 PM (Very curious about this one, might switch out for the "What's new" session). Achieve Hardware Independence with an Object-Oriented HAL - Thu 2:15 PM Practical Applications of Web Services in LabVIEW - Thu 2:15 PM (Also very curious...man the 2:15 slot on Thursday is tight) There are a few others which I'm curious about but have absolutely no bearing on my job (re cellphones!), so I'll not end up attending them. But man, for Wednesday afternoon I could really use a pair of clones.
-
Event registration is destroyed too fast
mje replied to Ton Plomp's topic in Application Design & Architecture
This is what most of my VIs do with the various sync objects (including dynamic event regs). The problem is this: Alpha is going to dynamically launch Beta, and needs some kind of sync object to communicate with Beta. It needs to know that once that object exists, it can be used and Beta will (eventually) receive all signals sent to it. Two solutions present themselves to me. Alpha creates the object and passes ownership of it off to Beta. I dislike this because it violates the destroy what you create practice, but it is the simplest way to solve the problem. Even if it's a dynamic event reg, if Alpha creates it, the reg is capable of receiving events even before Beta is ready to receive them. Alpha creates a temporary sync object to pass to Beta (usually a notifier to hold the final sync object reference), starts up Beta, then blocks on the temporary notifier. Beta starts, creates the permanent object which it owns, and signals Alpha using the temporary object, then continues on its way. Meanwhile, Alpha receives the permanent object reference, takes note of it, and continues on it's way, passing signals as appropriate. The second way is by far the more extensible of the two, but there is that added layer of complexity. Of course the whole situation is made much easier if we just don't care if Beta misses a few signals. In that case the ownership of the sync object can be managed by Alpha. -
You can register for individual sessions? How? I have my schedule planned, but wasn't aware there was any actual per-session registration.
-
Allow user to specify location of "LabVIEW Data" folder
mje replied to mje's topic in LabVIEW Feature Suggestions
Awesome. You guys rock, I never saw that option. Thanks a bunch! -
So, I've been working at home today, and LabVIEW has been an absolute slug of a beast when connected to my VPN. I think I tracked it down that it's because NI insists on keeping the LabVIEW Data location in the document root. If I disconnect from my VPN, LabVIEW runs like a champ, but as soon as I'm connected (meaning I'm no longer working off a local cached version of my documents, but a live remote version), LabVIEW freezes up for a split second every five seconds or so. If something large is being serialized, the IDE can freeze for up to the better half of a minute at a time. It's absolutely infuriating. This results in a painful development process. I must disconnect my VPN all the time so I can use the IDE. But then I must reconnect so I can commit changes, etc, then disconnect, reconnect, disconnect, ad nauseum. I mean really? Who stores information like that in the document root anyways? Why can't I put LabVIEW Data somewhere off my user root, like I don't know, in the LOCAL applications settings, which is where it should be anyways?
-
Event registration is destroyed too fast
mje replied to Ton Plomp's topic in Application Design & Architecture
Indeed. But still realized that even if you insert a long wait, there is still no guarantee your consumer will execute. If the system is under load from another process (LabVIEW or otherwise), a few seconds still might not be enough. The behavior is by it's very nature undefinable. As LogMAN said, you can also consider adding other synchronization functionality. Passing an occurrence or rendezvous as part of the stop event works, and then the code that trips the stop event can wait for the sync object to be properly signalled before destroying the event registration. But I still believe letting the consumer handle the unregistration is the best way to do it. For the very reason your code is giving you problems, I try to always tie event unregistration with the same event structure that owns/uses the registration. -
Event registration is destroyed too fast
mje replied to Ton Plomp's topic in Application Design & Architecture
I don't think this is a bug at all. You've programmed a race condition. Even with the delay call, your code's behavior is undefined. Signaling the event (or generating/broadcasting it in LV language) obviously won't wait for the event to be processed, but it's important to also realize that it doesn't even wait for the event consumer(s) to be invoked. The event is entirely asynchronous. Broadcasting simply queues the event up for each registered consumer of the event. With no wait, your VI will (usually) just blow through the broadcast, then go ahead an unregister the event, which will destroy the event queue, in the process neutralizing the uninvoked event (along with any other events in the queue). Add in a wait as you show, and your program will sometimes yield to a context switch allowing your consumer code to invoke, but you can't be certain it always will. The code behavior is by its very nature undefined. To avoid this, you can handle event unregistration in the consumer portion of code. Once the consumer receives the event, it unregisters itself and finishes up. -
I can't say I know exactly what the native DAQmx Task Name type is, it might be equivalent to a string, but there also might be underlying info which can't be resolved via the cast (though it seems to work...no idea how robust it is). As such I'd go with the implicit cast, if for no other reason than historically implicit operations can be faster.
-
Are you looking for session times? I'm not sure how final that list is.
-
Building an Installer Source Problem
mje replied to mje's topic in Application Builder, Installers and code distribution
Ah, I was not aware of the different versions. That makes sense. It's possible a hardware configuration on my core development PC triggered a different DAQmx install, which automatically gets included in the build now. I'll have to play and see if I can force the minimal version to be included. It's still a mystery though how the same source setting can produce two entirely different installers. This simply should not be. A source, is a source, is a source. If something external to the source dictates the resulting build, that something should be a part of the source. Near as I can tell, I don't have any control over whatever that "something" is in my build settings. -
Building an Installer Source Problem
mje replied to mje's topic in Application Builder, Installers and code distribution
Well, after all that, it seems my installer has tripled in size. It went from a "reasonable" 366 MB (*cough*), and for some reason is now 998 MB. It contains my exe, along with the LVRT, NI DAQmx, and NI MAX. I even went back and checked out previous versions of my code, sure enough, things that used to create 366 MB installers now magically create 998 MB ones. WTF? Is there any way of poking around a built installer and seeing what's going on? -
For static variables, I make a functional global member VI (or LV2 style global, if you will).
-
I browse this forum almost exclusively by using the active content link. It doesn't work when using a mobile browser (if the browser identifies itself as mobile). Starts with a warning stating "invalid argument supplied for foreach() in /home/lavagorg/public_html/cache/skin_cache/cacheid_3/skin_search.php on line 148" Then a bunch (5) of warnings pertaining to not being able to modify the http header after the header has already been sent are issued. In the end, I see the shell of the mobile skin rendered, but it lists no content. Not sure if the skin you use even supports the active content page for mobile browsers, but it sure would be nice if it did...
-
Building an Installer Source Problem
mje replied to mje's topic in Application Builder, Installers and code distribution
Bah, turns out it was asking for the SP1 download I did a while back. So I need to keep those around too? Rediculous. Never mind that as a development computer the stuff should already be on there... Absolutely ridiculous. I can't believe the build scripts are still in such a condition. -
I'm trying to build a distribution, and as usual, the NI build keeps demanding disks with names which have no bearing on reality. I managed to locate two of the three required sources, but the last one I'm coming up with nothing. It's now demanding "NI LabVIEW 2009 Service Pack 1 (SP1), Disk 1". I'm now sequentially going through every disk from Q12009 and later for the second time. None of seem to satisfy this requirement. It's beyond me why NI still can't figure out a way to include this stuff when I install the IDE to begin with. I hate having to track down these disks each time I add some feature to a build, especially when the names of the disks it asks for NEVER are the same as the names printed on the disks, and how quickly disks build up each quarter. It's a guessing game, and this time I don't know how to win. Invalid location for "NI LabVIEW 2009 Service Pack 1 (SP1), Disk 1". Try again? My computer is one more dialog away from learning to fly...