Jump to content

QueueYueue

Members
  • Posts

    68
  • Joined

  • Last visited

  • Days Won

    7

Posts posted by QueueYueue

  1. I thought of a quickdrop tool at first as well. The problem with that is you'd have to select the wire, the do a ctrl+space. This would bring up a generic quickdrop. Now you'd need to do what? If you start typing, it just does default quickdrop search. It's not possible (as far as I know) to use a plugin to change what is searched. So maybe instead of typing you hit a quickddrop shortcut. Ok, now we have a list of methods, how do I display them? Can you just populate the quickdrop combobox? I could never figure out a happy way to make the plugin work, so i ditched quickdrop all together.

  2. .... It appears that instead the compiler is breaking the loop up into sections of some predetermined length and then giving those sections to different CPUs. The length of the sections also appears to decrease with each iteration of processing as the jagged line become less pronounced as you approach the end. ...

    What you're talking about is called "Chunk Size"

    Notice when you enable loop parallelism, you get a radio button that defaults to "Automatically Partition Iterations". You can however change it to "Specify paritioning with chunk size ( C ) terminal".

    If you specify the paritioning, you'll get to specify how many iterations are in each chunk. The compiler will then break them up into chunk. Each "thread" (sometimes that means processor, sometimes not) will execute it's chunk, then grab a new chunk from the pile waiting to be processed, and repeat. Obviously there is some overhead to this. That means that you may not want to set the chunk size to 1, which would result in ultra parallel execution, but you'd get hit way more by the overhead. You also don't want to set the chunk size to P (meaning the total number of iterations), that means that 1 thread will get assigned all the work, and the other will just sit there waiting!

    By default LabVIEW uses large chunks at first, then smaller chunks at the end. This hopes to minimize overhead, at the beginning of the process, then to minimize idle processors at the end. Honestly, 90% of the time, it is probably best to leave it like this.

    Here's an example to illustrate why chunk size matters. Lets say you have 2 processors (meaning P=2) and you have 10 iterations to perform. Lets say that the default chunking algorithm says first go each processor will get 3 iterations, then the remaning 4 iterations will be in two chunks.

    First we'll assume that each iteration takes exactly 100ms to execute. That means that each processor will first get 300ms of work to do, then go back and pickup 200ms of more work to do, so the total time to execute: 500ms. Easy

    Now, let's saythat each iteration takes exactly 100ms to execute, except for one randomly determined iteration. The randomly determined iteration will take 5000ms.

    Making the assumption that random long iteration gets into one of the first set of chunks (the ones that contain 3 iterations each). So when the processors execute their chunks, processor 1 will have 300ms of work and processor 2 will have have 5200ms of work to do. While processor 2 is chugging through it's work, processor 1 will finish it's first chunk, and ask for another, it'll get 200ms more work to do. After that 200ms, processor 2 is still chugging away (we're only 500ms from when we started) so processor 1 is assigned the last chunk, it does it's 200ms of work, and then sits idle. Finally after the 5200ms, processor 2 finishes, and our loops stops execution.

    so what if we specify chunk size as 1. Best case senario: processor 1 or 2 gets the long iteration on the first chunk it gets. So that processor works on it, while the other processor chugs away on all the other chunks. This means one processor will do 5000ms of work while the other does 900ms of work. They are executed at the same time and the loop takes a total of 5000ms. Now if we get unlucky and the long interation gets into one of the last two chunks, then processor 1 and two will do 800ms of work before one of them hits the long iteration, so our total time of executiong is 5800ms.

    obviously there are a few other ways of this situation playing out, depending on what iteration gets the long instruction and what chunk that falls into. Just some food for thought.

    • Like 1
  3. Nice! I expected it would be something simple like that. Didn't have time to investigate myself.

     

    Only thing I'll add is that you need to close your references to all of your .Net objects (i count 3, Barcode reader, bitmap and results)

     

    I love when a .NET object does exactly what you need it to.

  4. Abstract classes and final methods are supported, a static dispatch VI is very similar to a final method. But interfaces would be really nice.

    Another idea: Duck typing. If we could cast between objects that provide the same public methods but are otherwise unrelated we wouldn't even need interfaces :-)

     

    They aren't.

     

    Abstract Classes: There's no way to say "you're not allowed to drop this class by it's self". Maybe that same checkbox that i suggested for constructors would allow this. Then again, you'd also need a way to make sure that a default value for a tunnel never created a new instance of my abstract class (i'm sure there are a few other special cases that would need to be addressed)

     

    Final methods: Static methods are close. If my class has a method that I don't want overriden, i just make it static. However, if my parent(parent.lvclass) has method "doSomething.vi" and it is dynamic dispatch, my new class(child.lvclass) can override. Let's say however, that I do not want anything that inherits from child.lvclass to be able to override "doSomething.vi". In child.lvclass i would mark "doSomething.vi" as final http://stackoverflow.com/questions/797530/c-sharp-is-it-possible-to-mark-overriden-method-as-final

     

    I'll vote for interfaces way before i'll vote for duck typing.

  5. The only one of these that I'm on board for would be constructors.

     

    Although it is possible to create a VI that is called something like "initialize.vi" or even "classname.vi" there is no way to guarantee that someone calls it. They can still just drop a class constant. It's possible to enforce something like this if you use a by reference scheme (using the "Restrict References of this class....." checkbox) but then you're doing things by reference. If there was a checkbox that made it illegal to drop a class constant (except for in the class's methods) on the block diagram, then we'd be able to enforce this rule.

     

    Since we're adding OO features, my vote would be for abstract classes, interfaces and final methods/classes (I don't know the generic word for this).

    • Like 1
  6. Unfortunately, I can't contact Microsoft to have them change their IE Active X component :angry: , so I'll just have to live with it.

    I think this is pretty much always the case.

     

    Roflk, do .NET components behave the same way with respect to threading? I've recently had some success with tlbimp and i'm curious if that would change anything. I think for(imstuck) would have to use aximp since he's working with a control instead of just a component, but I'm not to sure about that.

     

    Tlbimp and aximp create a .net wrapper around an activex component.

  7. ... Is the event structure somehow being blocked by the ActiveX doing stuff in the UI thread....

    I'm not super good with the specifics of your problem, but this is whats causing your issues.

     

    I've seen similar problems where you're trying to use an activeX component to talk to galil motion controllers, but a lengthy UI task delays your activex calls.

  8. There is a difference between frameworks and design patterns. You seem to be asking me for a name of a design pattern, then you go on to talk about actor framework and such. These are two separate things.

     

    In terms of design patterns, honestly, I don't know patterns may have suggested. I've read up on the design patterns in the past and implement them as needed. Usually you need to mix and match a bunch of the formal design patterns to implement your solution.

     

    Here are a bunch of design patterns: https://decibel.ni.com/content/docs/DOC-2875

     

    From memory about the solution I proposed, you'd probably use the following design patters: Template Method and Factory Patter.

     

    I'm trying to get at 2 main points here:

    1. Frameworks and Design patterns are not the same thing.

    2. You don't pick 1 design pattern. They are tools to help solve your problem. Use them as needed.

     

    Side note: I'm not a fan of the OO Plugin Framework. I don't think there is a good way to actually deploy these solutions.

  9. I'm pretty sure that what I originally suggested would still work even with the more specific details.

     

    Morel of the story: you want to keep all the TCP communication in the parent class, and then your child classes will be the ones to decide how to display/parse this data.

     

    Your INI file would would probably be used to build an array. The array contents would be instances of the children classes.

     

    If you want to do the "Several Data Displays at one time" Actors would be a pretty good fit. There is a bit of a learning curve, but basically it'd take care of a lot of the asynchronously spawning things for you. Don't use Actor Framework to try to teach yourself OO though. Learn OO first, then start to look into actors.

  10. You're a bit vague, so I'm gonna make as good of a recomendation as I can. It seems like this will be a really slick object hierarchy that will really help you out in the long run. I'm making 1 big assumption:

    That the TCP connection is opened at the beginning of the Manager class' lifetime (see below for class description) and closed at the end of the Manager class' life.

     

    note: when i talk about "tabs" i'm actually talking about changing the active VI in the sub panel.

     

    There are two main components in this implementation: An overall Manager class (the Top Level VI would belong to this class) and a set Clients.

     

    The Manager class would be responsible for opening the TCP connection, and passing that connection off to to the active Client. He will also create the "Stop" user event ref, and be the one generating events on it.

     

    Next, I propose you have a parent class called Client. This will handle all (or almost all) of the house keeping type tasks in private static methods. From what you've told me, here are the methods and access scopes I'd have for this class:
     

    Public Static:
    Run Client: This is the main entry point for the client. When the user changes "tabs", this is the VI that will be run. It will have an input of the TCP connection, a reference to the Sub panel and a "Stop" user event ref. All this VI should do is store the Active Connection it it's private data and then call the Insert And Run UI.vi with the sub panel ref and user event ref.

     

    Protected Static:

    Query Data: This should send a TCP string to the server to get the data. You do not want to make this dynamic dispatch. It's function is to generate a query string to send over TCP, wait for a response, and parse the response. It's supposed to handle the lower level stuff. The real question mark here is how do you generate the query string. It may be the case that they all have the same query string. This would be the easy case, then all you have to do is hardcode (or make a config paramter, whatever normal tricks you'd use) the query string. If they're not all the same, then you'll have to use the Generate Query String.vi method described below. Again, the goal of this function is to handle the writing/reading from the TCP connection. This will keep you from having to expose the active connection reference via an accessor VI, and more importantly, keep you from having to copy/paste code.

     

    Protected Dynamic:
    Insert and Run UI: This is an abstract VI. It should have an Input of the sub panel reference and user event ref. This is where all of your children will implement their UI. Each child should insert itself in the subpanel reference, then run it's UI logic. Make sure your child registers for the Stop User event ref and stop your UI when needed.

    Generate Query String: (optional) This is an abstract VI. Each child instance should override this VI and output a string that will be sent over the TCP Write buffer.

     

    OK, now that we have the parent all setup, all that we need to do is create children of the Client class for each "tab" you want. The only VI that they'll need to override is the Insert And Run UI, and possibly the Generate Query String. You'll write your UI pretty much as you'd normally would any other sub panel VI. The only extra thing you need to know is that you now have a built in Query Data VI that will auto-magically query the server and get back the data for you. Call this VI whenever you need to update the data. 

     

    If you need to add a new type of UI in the future, then just create a new child class and override the one VI. You'll only ever need to mess with the specifics of TCP and stuff the one time (when you're writing the parent class)

     

    Let me know your thoughts/question.

  11. NI documentation: http://zone.ni.com/reference/en-XX/help/371361J-01/lvscript/vi_bd_selection_change/

    I'm working on creating a development tool. What I want is to be able to know when the user selects something new on the block diagram of the VI they're developing.

     

    This is my thought process:

    1. Register for the VI Activation Event of the top level project.

    2. Open a reference to newly selected VI.

    3. Use the Register For Events node to register for the BD Selection Change on the VI ref that I just opened.

    4. Perform my action on the new selection.

     

    Seems like it'll work, but if I Click on the block diagram of a VI in edit mode i get the following error from the Register Events node 

     

    Error 1027, Saying "For the requested operation, the reference cannot be reserved as requested, is in an improper reservation mode, or the execution state must be set to running or reserved."

     

    I guess this isn't completely unexpected, it's not often you want to register for an event of a VI that's not running. This gets me thinking though, when will the BD Selection Change Event ever be used? You can't select something on the block diagram of vi that IS running, and you can't get events on a VI that ISN'T running.

     

    Am I missing something? See attached scratch code.

    post-27575-0-01892000-1367515592_thumb.p

×
×
  • Create New...

Important Information

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