07-14-2017 01:17 PM
@Jacobson-ni wrote:
Ben wrote:
I believe ( I have not used it lately) the DETT (desk Top Execution Trace Toolkit) will let you check the threads that code it running in.
Does the Time Stamp control fully block the UI thread? I thought it did in which case you can just check to see whether the DLLs continue to operate when you have the UI menu of the control open.
I complained and they fixed that "feature" where the Time Stamp control would run in the UI Thread. maybe 2016 was the fix?
Ben
07-14-2017 01:20 PM
That is the "worse case" scenario I mentioned above.
You can only have one UI thread in a process context but you CAN have more than one process context. Unfortunately that will requiring two applications that talk to each other ... via TCP/IP ? since queues will not work between multiple process contexts.
Put all of the dll stuff in an application that serves the widget and sends updates to the other process via whatever connection you decide to use.
Ben
07-24-2017 08:25 AM
I am still working on the problem. I have asked Alazar if it is possible to let their VIs run in another thread than the UI thread. I'm installing the DETT now, and upgrading my version of LV so that I can use the DETT. I understand now that I should not be using queues, but real-time FIFOs, since queues cannot communicate from or to a time-critical loop. So this is something I will change in my code.
Furthermore, I found a document in " Understanding the Priority-Based Scheduling Model (Real-Time Module)" This explains how many threads can run in which priority, and e.g. also that timed stuctures run at priority just below time-critical. And that I should not use times loops combined with setting the priority. But, I read now that the Real-Time module of LV 2017 can only run on the 32 bit version, which I have the 64 bit version. Which leads me to the following question: are there downsides to switching to the 32 bit version of LV? And secondly, If I'm working with at 64 bit version of LV, does this mean the Real-Time module and therefor all the execution system priorities do not work?
07-24-2017 08:27 AM
I am still working on the problem. I have asked AlazarTech if it is possible to let their VIs run in another thread than the UI thread. I'm installing the DETT now, and upgrading my version of LV so that I can use the DETT. I understand now that I should not be using queues, but real-time FIFOs, since queues cannot communicate from or to a time-critical loop. So this is something I will change in my code.
Furthermore, I found a document in " Understanding the Priority-Based Scheduling Model (Real-Time Module)" This explains how many threads can run in which priority, and e.g. also that timed stuctures run at priority just below time-critical. And that I should not use times loops combined with setting the priority. But, I read now that the Real-Time module of LV 2017 can only run on the 32 bit version, which I have the 64 bit version. Which leads me to the following question: are there downsides to switching to the 32 bit version of LV? And secondly, If I'm working with at 64 bit version of LV, does this mean the Real-Time module and therefor all the execution system priorities do not work?
Best Regards,
Judith
07-24-2017 09:09 AM
Maybe you can help me understand the reply from Alazar. I asked if their VIs can be set to run in a different thread than the UI thread. their answer: " It is possible to call the AlazarTech API functions in a different thread than the LabVIEW GUI thread. Please note however that the functions from our library are designed to make user-side threading unnecessary. This is because all API functions except AlazarWaitNextAsyncBufferComplete are non-blocking. AlazarWaitNextAsyncBufferComplete itself can be made non-blocking by using a timeout value of zero."
Does this mean that where I call their VIs from determines on which thread it runs? So setting the execution system for each of their VIs is not the way to go? but should I put the code with all their VIs in a subVI and set the execution system there?
If their functions are non-blocking, that means they won't disturb other processes? But still, if it all runs on the UI thread, it does matter, right? Because it will be too much to all run on that thread.
Best Regards,
Judith
07-24-2017 09:43 AM
That reply reads as "Completely correct but totally useless". Are they a division of Microsoft?
If they have exposed the call library functions and you can access them to configure them to NOT run in the UI thread...
You can conduct an experiment that MAY help but will not be as good as them just answering the question...
"Are the API calls thread safe?"
An answer of "yes" would let you move ahead with more certainty. But if you can not get a straight answer you can TRY the following.
If you are not familiar with an Action Engine, start by reading this nugget.
Develop an Action Engine (AE) that implements each of the API calls. One action for each call type. make sure your application only uses the AE for all calls. Ensure that all calls of the API are marked NOT to use the UI thread.
Configure the AE to use any thread other than the UI thread.
If the code is thread safe wrapping all of the function calls in the AE will ensure that no two threads are trying to invoke the API at the same time.
Then you will have test the he@# out of it and hope you beat it hard enough to really test it. if their code is not thread safe, even the above could crash the code if one API call is done in one thread but another call runs in a different thread.
As I posted a while back, this sounds like the worse case condition and implementing another process with its own UI thread may be in your future.
Ben
07-25-2017 03:43 AM
Hi Ben,
thank you for your reply!
they say their ATSApi.dll is not thread-safe.
I will look into the Action Engine you mentioned (is that worth trying when it's not thread-safe? or will it always fail?), and test some things with the DETT, and if all fails I will start looking into implementing another process with its own UI thread.
Thank you so much for all the help so far!
Best Regards,
Judith
07-25-2017 09:28 AM
I am hard pressed to find a post from Rolf Kalbermatter that I BELIEVE is the person that first introduced the idea of wrapping a dll and setting the thread the AE will run in. But if memory serves me, he also said that it MAY work and it MAY crash.
If you r attempts to wrap it up in a AE that is assigned a non-UI-Thread fails, I would stat to get busy figuring out how to talk TCP/IP between applications on the same machine.
Keep us updated so that we can learn from your experience.
Ben
07-25-2017 10:05 AM
Thank you!
yes, I will look into it 🙂
and of course keep you updated. Thank you so much!
Best,
Judith
07-26-2017 03:43 AM - edited 07-26-2017 04:02 AM
After reading the whole thread more or less completely, I"m still not quite sure what the problem of the ATSAPI is.
Their first response claimed that it was possible to call the library from (a) different thread but not multiple functions at the same time. Then they answer that their API can be called from other threads but that it is designed to make user side threading unneccessary.
The problem here is likely following:
For some reason they would want to guarantee that their APIs are all always called from the same user thread. In LabVIEW there is only really one thread configuration that is guaranteed to always use the same thread and that is the UI thread. But running something like an interface to a fast DMA bound data acquisition in the UI thread is of course like having a Ferrari and driving on a congested highway in the morning peak hour.
What they should really answer is:
- Can the APIs be called from different threads? This would clarify if they use so called Thread Locale Storage (TLS) as an intermediate storage location between different API calls. (Most likely that is the real reason for requiring the nodes to be configured in the UI thread).
- Or is it really like they claimed in their first answer that the APIs are thread safe but never can be called in parallel? That could be for instance the case if they use so called sessions (handles, refnums) that you have to pass from one API to the other and in which they store internal settings for that session. If access to those sessions is not protected, then it could be problematic if the API is called in parallel from multiple locations.
If the answer is the first then there is indeed a serious problem. A wrapper DLL could solve that by adding (another) handle to all API functions that would restore and save the TLS environment before calling the actual API. However this is heavy C programming stuff and not likely worth the effort. NI does have an example for their NVIDIA CUDA GPU Analysis Toolkit for writing your own extension DLL for that Toolkit. The NVIDIA CUDA API makes internally use of TLS and in order to not have to set the Call Library Nodes to run in the UI thread NI shows in those examples how to setup the TLS correctly so that the NVIDIA API always sees the correct TLS setup no matter from which LabVIEW thread the API is called.
If the answer is the second there are two possibilities:
Data flow in LabVIEW does prevent functions from running in parallel. If you are careful to never call two of those APIs in parallel by wiring them in such a way that they need to run sequentially, you already made sure that no API call can happen in parallel. For instance by wiring the session (handle or refnum) and the error cluster through each of them and then from there to the next VI, you already have guaranteed that the functions can not be called in parallel and would be able to change the Call Library Nodes to run in any thread. The downside of this is that YOU are now responsible for making sure that you wire the functions in that way. If you don't you can introduce errors that may not even happen for a long time, until you ship your application to the other side of the globe and suddenly it starts to misbehave in strange ways.
The other possibility is to create an Action Engine as what Ben suggested. If you don't set the Action Engine to be reentrant, it will block anyone from trying to run one of its methods while another method is busy. This is not the most elegant solution. AEs were great in the old days where no LabVIEW GOOP was available but I have since come to not rely on them that much anymore since they really set the OOP design principle on its head. They have only two advantages above LabVIEW GOOP nowadays:
1) They can wrap an API in such a way that it can be called from any thread in LabVIEW but guarantee that only one call into the API can be made at the same time.
2) They use significantly less VIs than any equivalent GOOP API, but this is mostly a moot point nowadays.
The AE takes extra time to create, makes handling your API potentially more cumbersome and the biggest drawback of AEs is that they tend to grow into monsters since the connector pane of the AE needs to accommodate any and all parameters from all the methods you want to wrap. The advantage to relying on proper sequencing through data flow wires is that you can not accidentally use the API in a way that violates the "don't call me in parallel ever" rule.