Jump to content

Mark Smith

Members
  • Posts

    330
  • Joined

  • Last visited

  • Days Won

    5

Everything posted by Mark Smith

  1. The only time I've had to worry about thread exhaustion is when making interop calls to .NET/DLL/COM. LabVIEW will grab a thread for the interop call and not release it until the call returns. If you make simultaneous calls to DLLs (assuming they are thread-safe and not called in the UI thread), LabVIEW will allocate a thread and not return that thread until the DLL call is complete. This can lead to thread starvation and blocking if the DLL call takes a non-trivial amount of time to complete and you reach the thread limit for a given execution system. DAQmx is susceptible because it's all calls to the DAQmx DLL under the hood. Mark
  2. As Rolf said in the referenced post, the GAC is the only sure bet for a .NET DLL (assembly). I presume the MySQL assemblies are signed and can be installed in the GAC. If MySQL won't install to the GAC automatically (I suspect it will) you'll need to include an installer that will install a .NET DLL to the GAC because the LabVIEW installer won't. The installer can be built from Visual Studio -most any version. Mark
  3. I wrote some code years ago using the System.DirectoryServices to query the MS ActiveDirectory. I think querying LDAP might be similar, That code is in the LAVA code repository at http://lavag.org/files/file/49-activedirectorytools/ if you want to take a look. Mark
  4. The Desktop Execution Trace toolkit (http://sine.ni.com/nips/cds/view/p/lang/en/nid/209044 ) will help you find memory leaks in LabVIEW. It can show all the memory allocation and deallocation that LabVIEW does. If it's not LabVIEW leaking memory (if it is the .NET DLL) then maybe the Process Explorer (http://technet.microsoft.com/en-US/sysinternals) can help. Or maybe one of the other SysInternals tools - it's been a while since I needed them and my memory may not be accurate. At any rate, that toolset can be very valuable to a Windows platform developer. Mark
  5. We've had reasonable luck using hard to call from LabVIEW COM implementations by wrapping them in .NET and then calling the .NET DLL/Assembly. It's pretty quick to create the .NET wrapper and try it and it may just work. See this link for details http://msdn.microsoft.com/en-us/library/ms404285.aspx Mark
  6. OK - I see what you see and concur - it shouldn't get closed before the loop exits. I'll blame it on old age and bad eyesight
  7. Rolf, On the attached picture, the ref wire from the _SmaoMain property node used to get the ref to the SmaoMain.Info property goes around the While loop where the Enabled Devices get queried and into a Close Ref. There's no data dependency I see that would keep the Close from operating on the Initialized _SmaoMain object before the property of that object gets queried. If the object that contains the property data gets closed, wouldn't the data associated with that property likely get disposed as well? Am I missing something obvious? Mark
  8. Looks to me like you close the ref to SMAOMain in parallel with the loop you use to try collect the Enabled Drivers info. Once you close that ref, your SMAOMain object gets cleaned up and you're likely looping on a closed ref to the SMAOMain.info property when you try to get the enabled drivers. Mark
  9. If all you need is a sine wave (or other standard functions), a fairly inexpensive alternative is to use a function generator instead of a analog out device capable of arbitrary wave forms. Maybe something like this http://www.amazon.com/Velleman-PCGU1000-2MHz-FUNCTION-GENERATOR/dp/B0011E5RNO/ref=sr_1_1?s=hi&ie=UTF8&qid=1381783997&sr=1-1&keywords=pcgu1000 $165 on Amazon
  10. It may be obvious and you already are doing it, but make sure you are releasing those queue refs you obtain by name or you can create a small but sometimes consequential memory leak. It's bitten me in the past. Mark
  11. The problem is that you can't instantiate an abstract or interface class. The ICollection interface requires you to create a class that implements the ICollection interface. See http://msdn.microsoft.com/en-us/library/ms173156(v=vs.90).aspx For more explanation. I don't have Visual Studio handy or I'd write a brief example. Let me know if you need the example and I'll get to it. Mark
  12. Would you like to also " ... create gigaoptimal code in nanotime to make megabucks."? Check out http://mooregoodideas.com/mgi-efficiency-toolkit/ for some ideas - not necessarily good ones...
  13. I followed this topic with interest but didn't have anything to add until today. I was looking for some C#/.NET code to support a project and found a nice library in the Code Project. Since this thread had got me worried about using third-party code and licensing, I took a look at the license under which it was released. After reading this license, I think it's a pretty good model and easy to understand. I can use the library as is or derive from it with the restrictions that I don't remove the original author's attribution, I don't try to pass this work off as my own, and I include a link (somewhere) to the license agreement. http://www.codeproject.com/info/cpol10.aspx Mark
  14. I can't imagine why one couldn't call a static method from a .NET assembly from any .NET language. I'm wondering from the questions you ask if the wrapper dll your customers write is a COM wrapper, since no, you can't just register a .NET assembly as a COM object and have it show up through an ActiveX type interface. So maybe they want to call the .NET DLL from an unmanaged context (C++ maybe?). You can, it appears, make your .NET DLL COM Visible (see "Exposing .NET Framework Objects to COM", http://msdn.microsoft.com/en-us/library/zsfww439.aspx), but not directly from LabVIEW as far as I can tell. You would have to do the work explained in the link above using Visual Studio or such. Alternately, you can build a LabVIEW exe as an ActiveX server and that will show up as a registered COM component, but that's a whole 'nuther can of worms. It works, but it ain't pretty.
  15. When I tried the event registration refnums, they were private data in one of my classes so they needed accessor VI's to be of use to any VI that wasn't a class member. That means that I had no choice except to share the event registration refnum, which turned out to be a bad idea for my use case since it doesn't really allow multiple subscribers. If I just expose the event refs,then its easy for any VI that wants to consume the event to subscribe. I don't find it ever necessary to preload event queues since I don't use the events for any kind of input control - they are only used to publish data to subscribers. More importantly, how do you accomodate multiple subscribers?
  16. If you stuff the event registration with events and then wire that event registration to more than one event handler (as one might, in a publish-suscribe tye design), how do you ever know which event structure will handle which event? It has been my empirical observation that you can end up with a scenario where 1) you load events into your event registration ref (mailbox) 2) you wire that node to more than one dynamic event terminal 3) One event structure registers first and goes and empties the mailbox (event registration) before the other event loop gets a chance to check. As far as I can tell, this happens because the event queue has only one registered listener when the events are consumed so it discards the events as soon as the first event structure consumes them. Or, I have even observed behavior where it appears the second event handler gets there somewhere in the middle of emptying the mailbox and gets some but not all of the events that were registered. I got nervous enough about this sort of thing that I stopped exposing event registration refs and just expose event refs in my designs. It can't handle the scenario you described, but I don't trust using events that way in a publish-suscribe type architecture where there are likely to be multiple listeners for any event.
  17. I don't think your limiting factor will be passing the data whether you use queues or events - the most resource intensive activity will be the graph display front panel updates no matter if they occur in the main message handler or a sub-vi. Edit - one issue you may run into passing the data thru a queue or event to a sub-vi is making inadvertent copies of the data that would not happen if you display in the main VI. Just something to watch out for.
  18. Not sure what you mean here about events not working in subpanels - I've got more than one project that uses subpanels and and the subpanel will handle most any front panel event (save for the keydown event - that one always gets handled by the calling VI) and any user-defined event I've tried. As far as AlexA's question, I've found it easier to just expose the events and let the subvi's handle registration rather than using the event registration refnum.
  19. Check out the XML-RPC Server in the Code Repository for an example of a server that can accept mutiple clients ( ) . You shouldn't have any problems accepting mutiple connection requests from the same IP to the same server port, as the server should establish a unique connection (socket) for each request. Mark
  20. I think mje pretty well summed it up, but the explanation I like the most is from AQ on this NI blog (https://decibel.ni.com/content/groups/large-labview-application-development/blog/2012/06/02/when-should-the-to-more-specific-or-preserve-tun-time-class-primitives-be-used-with-oop-in-labview) describing the difference . The post referenced is worth a read as well. "...The "To More Specific" tests the incoming object vs the type of the wire at the middle terminal. The "Preserve Run-Time Class" tests the incoming object vs. the type of the object on the wire at the middle terminal. "
  21. I think you'll need at least one thread for every .NET DLL call you want to run asynchronously to avoid blocking by the .NET DLL calls. LabVIEW can schedule multiple activities on one thread for internal calls so if a VI goes dormant while waiting that thread can be reassigned to another as long as all of the code is native LabVIEW. This isn't true for DLL calls. LabVIEW can't reuse the thread assigned to the .NET call and must wait for it to return. So as soon as there are more .NET calls than threads assigned for the execution system they run in, someone has to wait. You can set the number of threads per execution system using the vi.lib\Utility\sysinfo.llb\threadconfig.vi referenced in the first link Ned pointed to. If you need more threads than can be assigned to one execution system, then you may have to split the .NET calls across multiple execution systems. Mark
  22. I'm pretty sure it's because you can't type cast any cluster that has a variable length element - if you add a string to a cluster, the type cast won't accept that as a vaild input, either. From the LabVIEW help on flattened data "LabVIEW converts data from the format in memory to a form more suitable for writing to or reading from a file. This more suitable format is called flattened data. Because LabVIEW stores strings, arrays, and paths in handles (pointers to pointers in separate regions of memory), clusters that contain these strings and arrays are noncontiguous." A basic type cast operation just tries to take a chunk of memory and change the type associated with that chunk. I don't know the internal implementation of the LV type cast, but I'm sure it's more involved and does checks on the validity of the cast. But still, since the memory chunk containing the elements referenced above is not contiguous, you can't just call that memory chunk a new type (like a string) since that chunk doesn't contain all of the data referenced by that type.
  23. This is working exactly the way one should expect. If you have a fixed size array that you need to pass (it's always the same size) you can use a cluster instead of an array. LabVIEW will flatten a cluster of simple types into a stream without adding any length element. If your data array may be different sizes on each call then you're doing it the only way I know of. Mark
  24. I don't use the complete path to the class - I strip the class name so a class like TempSensor.lvclass would have config file named <Public Application Data>\MyProject\TempSensor.ini or something like that. And the reason I use the <Public Application Data> is that it works on all the Windows targets I use for all users (don't need admin rights to modify). I don't have to deploy to Windows embedded, so I can't speak to that, so your needs may be different. Mark
×
×
  • Create New...

Important Information

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