Multiple Thread (Sequence) Interaction


RodSwan

Recommended Posts

I have two sequences that I think have just exhibited an undesirable interaction.

 

Sequence A, thread priority 5 triggered once per second with a BeginSeq() in a channel event. This sequence increments a second channel (Counter) that is defined as a device type "Test" I/O type D to A....

 

Counter += delta

 

Sequence  B, thread priority 2 is triggered perhaps once per hour with a BeginSeq() in an event on a third channel (and sometimes by the UI) which resets the counter...

 

Counter = 0

 

In 5 years of using Daqfactory this has worked without error.

Today I find an instance yesterday where, whilst all other actions in both sequences worked as expected, the Counter did not get reset.

 

Only explanation I can think of is that after low priority Sequence B had updated Counter to 0, high priority Sequence A had overridden the 0 with the incremented value based on the pre zeroed value.

 

Is that possible?

 

A solution would be for me to set a flag in the low priority sequence to tell the high priority sequence to do the reset to zero but is that really necessary?

 

 

Rod.

Link to comment
Share on other sites

Yes, that is definitely possible.  DAQFactory protects the variable from getting totally corrupted due to multithreading, but it doesn't protect against this sort of thing.  Internally, when it increments, it goes out and gets the current value of counter, adds delta to it, then puts the result back into counter.  Its entirely possible that between the getting and the setting, the system task switched and the other thread set the counter to 0, which then got immediately overwritten when the increment sequence resumed.

 

Its important to understand also that Windows is not a true preemptive multitasking OS.  Also, since most computers now are multicore, you can't use priorities to control execution order.  Its entirely possible that your priority 5 sequence was running on one core and your priority 2 sequence was running at the same time on another core.

 

Using a flag unfortunately won't work because there is a small delay between when you check the flag and when you raise it.  This is the same delay that caught you in the first place.  The only really way to protect against this is to use a mutex or critical section.  The only way to implement one in DAQFactory (outside of importing a DLL with that functionality) is to create a dummy serial / ethernet device and use its lockPort() / unlockPort() functionality.  These are essentially mutexes with short timeouts so calling lockPort() doesn't completely block.  You'd do something like this:

 

while (!device.myMutexDevice.lockPort())

   delay(0.01)

endwhile

counter += delta

device.myMutexDevice.unlockPort()

 

and in the other its basically the same:

 

while (!device.myMutexDevice.lockPort())

   delay(0.01)

endwhile

counter = 0

device.myMutexDevice.unlockPort()

 
That all said, you have another choice.  Just wait 0.1 seconds after resetting the counter and reset it again.  Since the counter doesn't get incremented again for a second, this should eliminate the problem.  It may overwrite once, but not twice:
 
counter = 0
delay(0.1)
counter = 0
 
You could probably delay 0.01 seconds.
Link to comment
Share on other sites

hmmmm. Yes I understand  its as I thought.

I think my solution to use a flag to tell the higher priority sequence to do the clear would probably work (and is a lot easier than your dummy serial device) ....

 

Low priority Sequence:

       ClearCounter=1

 

High Priority Sequence:

       If ClearCounter==1

              Counter=0

              ClearCount=0

       else

              Counter += delta 

       endif

 

but I like your second choice better :-)

 

Thank you.

 

Rod.

Link to comment
Share on other sites

Yes, using a flag so that counter is only changed from one thread will eliminate the problem (though the syntax in your script is wrong, you need () in the if.).   I was picturing you using a flag to tell the other sequence not to make a change, basically as a mutex and that won't work.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.