LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Multi-threading status

I'm dabbling with the CMT library and having good success. One thing I'm not clear on is the proper way to retrieve status of a threaded looping function. 

 

Currently, I'm just using globals. I publish indexes, values, and step status inside my thread function, along with a "fresh" stats flag (so that my main thread knows it's new status).

 

This seems to work well. But I'm aware that this is very unsafe.

 

Is there some preferred method of doing this? Should I be looking at TSVs? That whole method seems difficult. 

 

0 Kudos
Message 1 of 5
(951 Views)

One possibility is the threadFunctionData pointer that you can pass to functions like CmtScheduleThreadPoolFunction(). This pointer is also passed to your Thread function that you install. Instead of globals you can simply allocate a memory block for a structure or similar, pass it to the Thread install function and then access it from your main program and the thread function itself. You still need to make sure to protect data that is bigger than a CPU register (32-bit or 64-bit) or spans over the natural alignment for that size, if it belongs together and needs to be interpreted as one data set.

Rolf Kalbermatter
My Blog
0 Kudos
Message 2 of 5
(874 Views)

Globals in a multithread prog are BAD, unless each access (read AND write) is surrounded by a lock (unless <32 bits like Rolf said)

I recently wrote a CVI library that was used in a multithreaded webserver and crashed as soon as 2 concurrent accesses occured. It was solved elegantly by replacing all globals (I had none) and local statics with:

thread_local static struct json_object *obj=NULL;

(didn't compile on some systems) or (compiles everywhere AFAIK):

static __thread struct json_object *obj=NULL;

0 Kudos
Message 3 of 5
(829 Views)

Thanks for the inputs.  In my case, it's a single client and single application.  It has a RS232 asynch serial connection to a piece of hardware.  At one point in the test, it does a ~120 second long acquisition, so the receiver is in a for loop.  During this time, the GUI will completely "hang" even with using ProcessDrawEvents inside the loop.

 

So now I'm starting another thread with CmtScheduleThreadPoolFunction that writes to a TSQ.  I then also use CmtWaitForThreadPoolFunctionCompletion to wait for it to get done, with OPT_TP_PROCESS_EVENTS_WHILE_WAITING option to be able to quit the loop if needed.

 

What's not clear to me is how that Wait function works in conjunction with the Process Events option.  Does the call stack down to the Wait call not get re-entered?  Just other events?

 

In my app, there are other tests that run sequentially, all of which made serial connections to the hardware.  So I need them all to wait if this loop function is running, yet I want the GUI to be responsive while it runs.

0 Kudos
Message 4 of 5
(822 Views)

Handling the long process in a separate thread and passing back information to the UI thread via a TSQ should guarantee by itself that the UI remains responsive during this operation: isn't it?

 

If the separate thread can be structured in a state machine, the command to abort the function could be implemented in a toggle button that the machine tests on every iteration: this will avoid the need to use a global variable for this.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 5 of 5
(810 Views)