Timer.CallLater Not Preemptive Thread Safe

All - FYI - Timer.CallLater is not thread safe. William Yu just told me that in a bug report this morning.

Not sure yet how to invoke code on the main thread from a preemptive thread outside of the AddUserInterfaceUpdate method.

Timer.CallLater is a convenience function; it would be straightforward to roll your own using a Timer.

Sure. But if timer.call later is not preemptive thread safe, is calling a timer function of my own going to be preemptive thread safe?

If Timers are preemptive thread safe, then it should work.

Why not simply use AddUserInterfaceUpdate ?

1 Like

Yes, a Timer is safe, I use it in ThreadPool.

What you can’t do is reuse a Timer with Timer.RunMode = Timer.RunModes.Single. If you need to reuse it (that let it fire once and turn it on again sometime later), use a Semaphore/CriticalSection to protect changing the mode to RunModes.Multiple in the Thread, then change it to RunModes.Off in the Timer, protected by that same Semaphore/CriticalSection.

For example, in the Thread:

TimerSemaphore.Signal

MyTimer.RunMode = Timer.RunModes.Multiple

TimerSemaphore.Release

In the Timer.Action:

TimerSemaphore.Signal

me.RunMode = Timer.RunModes.Off

TimerSemaphore.Release

// Do the stuff the Timer needs to do

Edit: This is how I got around the problem in early versions, but I don’t know for sure if this is still required.

2 Likes

Oh, I could but would likely need to create delegate methods to handle different main thread functions. Or I suppose I could put it all in one and just decide what to do based on the dictionary passed…

I just haven’t thought through the solution yet in my code…

I guess you will find a solution using this “tunnel” to the UI thread.