I've been using multithreading a lot in a large data-acquisition and motion-control program that I'm working on. There are various reasons, but the speed (or rather lack thereof) in the GUI seriously slows down data acquisition and processing if I try to run everything in the main thread. So, I've got the main thread that handles the user interface; the DAQmx data acquisition thread; and a data processing thread that runs in the background, accepts the data (which comes in at regular intervals) from the DAQmx thread, processes it, and stores it for display and saving to disk.
Anyways, with all of this I make heavy use of the multithreading utilities in the utility library, especially the Thread Safe Queue functions, threadlocks, and the threadsafe scalar variable macros. They work nicely, but 45% of my debugging now consists of finding all of the spots where I forgot to release a variable after locking it, forgot to release a pointer after locking it, or forgot to close a queue after starting it.
Another 45% consists of finding places where I call a function from two different threads, for instance if I start up a window in one thread, and try to call a function for that window in another thread (for instance: calling the main callback function for a panel with the CLOSE event to force it to close when shutting down the main program, for forcing a button-press with the COMMIT event) which doesn't always work. Allocating a list in one thread and calling a function that reads from or writes to that list from another thread really doesn't work!
It would be very nice to have some help in CVI that can count the various threadlock and other thread-safe stuff openings and closings and tell me: "Hey, you forgot to release that one". Since 99% of the time these are locked and released in the same subroutine, it would be helpeful even if it just looked within routines.
It would also be very helpful to have some utility that can keep track of what thread a given function is executing in. Perhaps the best way to do this would be to simply implement a function call-tree utility, with some notation of threads in there; the main problems after all occur when one calls the same routine from two different threads, with different results for each.