I have a getting started / best approach question about a multithreaded application I am working on. I have an engineering background and have done a fair amount of programming, but have little formal training in programming and very little experience with multi-threading. Therefore I am trying to use the provided examples in Labwindows as the backbone of my program. I am specifically looking at the examples daqMT.c and asyncdem.c.
My application is as follows: I need to acquire, save, analyze, and display approximately 10 intracardiac electrograms from a multi-pole catheter using a stripchart in sweep mode such that it displays the signals in near-real-time. Typically we sweep about 1-3 seconds of data across the screen at a time. I then will be performing some fairly complex near-real-time calculations that would also need to be displayed in a few different ways (e.g. a phase-plot, an STFFT, a derivative of the signals, etc.) which also sweep across the screen in another 2-3 graphs in near-real-time.
I have not bought the hardware yet, but I plan to buy something like a USB-6211 to work with a laptop. The sampling rate will likely be 1-2 kHz per channel. At this time I am already working on the program and using previously recorded data as my simulated real-time signal. To date, I have successfully done this in a single threaded display with no analysis as of yet. I decided that since there are so many moving parts to this program, that it would best be multi-threaded.
I would like some general advice on the best way to set this up. My plan at this time would be to have the data acquisition (or reading previously recorded data from disk) in one thread, the analysis and maybe disk logging in another thread, and the user interface in another thread. I may even need more threads for each type of analysis -- not sure about this yet. Is it better to use the asynchronous timers used in the asyncdem.c program to set up the threads, or would it be better to follow the daqMT.c example. That example already is very close to what I need minus the data analysis and the sweeping graph. I guess I would have to use a hybrid approach by using the asynchronous timer to sweep the data across the screen.
Anyway, I realize I don't have a very specific question at the time, but if any of you have done something similar to this, I would very much appreciate any advice before I spend too much time on a wrong approach. Thanks. -philip
First of all, I want to remind you that all async timer functions run in the same thread.
So if you setup more than one async timers, they will actually share the thread.
I would suggest you to schedule explicit threads for each of your tasks (data acq, analysis, display)
A major headache in multithreaded applications is the security of the data.
Global variables are NOT good at this. So you have to use thread-safe queues (TSQ) or thread-safe variables.
CVI has built-in support for both. Check the function helps and example code.
Your flow will look like this:
-Data acq thread will read samples and put them into TSQ1.
-Analysis thread will check the size of TSQ1 periodically and read sufficient samples from it when data is available. It will analyse the data and put the samples to be displayed into TSQ2.
-Display thread will check the size of TSQ2 periodically and read sufficient samples from it when data is available and display them.
This is how I would approach the problem if I were doing such a project.,
Hope this helps,
Thanks so much for your suggestions. This actually helps me alot conceptually. What you are suggesting is similar to one of the example programs I am trying to reverse engineer, but I like the flow you are suggesting better. I will give it a shot.
The one thing I am having trouble wrapping my brain around is how to maintain these separate threads, while at the same time using a timer to sweep the resultant data across the screen using a stripchart so that it appears to be in real-time. I have done this successfully in a single thread (as demonstrated in the sample program 'stripchart.c'), but I'm not yet sure how to accomplish in multiple threads. You mentioned that all the asynchronous timers live in the same thread - does this mean their own separate timer thread, or the main thread, or can you specify which thread? I assume the timer lives in its own separate thread, so in order to trigger the display thread to update the strip chart, I guess you could use a thread safe variable such as PlotNextPoint = 1, or something like that. Or would it be better to use the timer's callback as the display thread, which plots the next point in TSQ2. I'm getting a headache thinking about it.
Either way, I don't see any way around using the timer if I want a smooth, pseudo-real-time waveform sweeping across the screen. I think my timer will have to be setup such that it matches the sample rate of the original data minus any screen decimation that is desired. This is much easier to do when you don't sweep the data, rather plot it in chunks at a time, but unfortunately, the application I am working on requires the sweeping. Would appreciate any additional feedback that you might have. Thanks again. -Philip
Actually my approach does not make use of the timers at all.
You will start your threads and they will run in a loop.
As soon as other threads pump data into TSQs, your display thread will start plotting data (sweeping).
You need a way to terminate the loop, which can be a thread-safe variable you can check at each loop iteration.