If the handle setup wasnt the issue, and the call setups look okay, I guess that gets me back to my original issue - why is the DLL crashing occasionally? Obviously you cant answer that for me, but I am wondering if there are any other tools I could look into to get more information about what is causing this, and what I can do to prevent it/recover from it.
I am also calling this DLL from multiple, parallel loops, (with the call setup to run in any thread) and I haven't been able to find anything that indicates this DLL is safe for parallel access. I am going to try removing the parallel access, by using a lock around all the DLL calls. Would I be better off just using the 'Run in UI Thread' call setup, or using my own lock (using semaphores)? My gut tells me using my own lock would be faster.. Thoughts?
From a brief look at the source code in the git repository it does not look very multithread safe.
And as a hardware resource you anyhow should not try to attempt to access the same interface from multiple locations in parallel. It can be ok to access different interfaces in parallel though the way they use global variables inside the DLL I'm not sure that would be safe too.
But no matter if the DLL is safe or not, accessing the same hardware interface from multiple locations in parallel is usually doomed unless the API around it takes special measures. That means not just making each function call in itself thread safe but protecting bus access as an atomic operation (acquire lock, send command, wait for answer, release lock), otherwise you end up receiving the wrong answers to your command request.
UI Thread safety is the quick and dirty way. It will make the API calls compete with everything else in LabVIEW that is serialized through the root loop thread, such as UI drawing, OS message loop handling, various VI server operations that are not thread safe and anything else that was put in the UI thread to have a quick and dirty serialization, including other Call Library Nodes where the programmer selected UI thread operation, either because it is needed or because he didn't know if it was safe to use "any thread" configuration.
Using your own semaphore allows the code to run in the normal default thread of the rest of your VI and not having to compete with all the other UI threaded operations, so yes it is likely more efficient but also more work to do, and you can potentially create mutual exclusion locks if you are not careful.
Ya, I didnt even bother trying with the UI thread - I just put in my own lock. The code is already a big mess with lots of unnecessary overhead, I don't want to add another item to the UI thread stack.