Heavy Timer in Separate Thread or Main Thread

This seems like a simple question and I suppose it is, but is it wiser to put a constantly running Period=1 timer in a thread other than the main thread? The purpose of the timer is to look for incoming events (in my case MIDI) and respond VERY quickly (no latency). So it’s polling really fast.

Again, is there any advantage to having it spin in a separate thread rather than the default main thread? I’ve been doing the latter for awhile and my UI’s seem unfazed by it.

Well, all timers action events on the main thread. So putting them in the thread will still have them fire there.

What’s the interface for MIDI, a serial port? You can’t use the serial port events for this?

[quote=127293:@Garth Hjelte]This seems like a simple question and I suppose it is, but is it wiser to put a constantly running Period=1 timer in a thread other than the main thread? The purpose of the timer is to look for incoming events (in my case MIDI) and respond VERY quickly (no latency). So it’s polling really fast.

Again, is there any advantage to having it spin in a separate thread rather than the default main thread? I’ve been doing the latter for awhile and my UI’s seem unfazed by it.[/quote]

I believe a timer always execute in the main thread anyway. So placing it in a thread seems futile.

Using a thread could be of interest if your UI is somewhat demanding and could temporarily halt the execution of the timer. A tight while-wend loop in the main thread could alter the execution of the timer (even stop it during the loop). Placing the poll in the thread will alleviate that issue.

I just tried using a simple system.debuglog in loop with a while-wend using ticks as timer in a thread run event, while the main thread was frozen by a while 1<2/wend. A timer placed on the page was halted, while the thread continued uninterrupted.

If your UI needs heavy lifting, you may want to do your fast polling in the thread.

Is this a limitation of Xojo, or questioned another way, why is that?

I use PortMIDIMBS. MIDI is a specialized thing and different than serial communication.

I asked this also on the MBS list, but what if I didn’t use a timer to poll for events. What if I did something like this:

do if Operate Then while MIDIStream.Poll <> 0 // handles MIDI info wend else Exit Do end if loop

And I spawned the thread by:

MIDIThread = new CMIDIThread MIDIThread.Operate = True MIDIThread.Run

And then when I wanted to stop the polling, just go MIDIThread.Operate = False. Now how would that affect the main thread?

[quote=127314:@Garth Hjelte]do
if Operate Then
while MIDIStream.Poll <> 0
// handles MIDI info
wend
else
Exit Do
end if
loop[/quote]

This is not a timer… It is a loop…

So, what is the difference between a timer and a loop, other than the (mostly) exact timing of a timer? I’m talking about polling, all I want is consecutive events. Whether I get that from a loop or a timer I don’t care.

A timer fires every so often, whereas a loop when it reaches the bottom immediately begins again. If you don’t give a loop for some way to exit, your app will appear to have stopped working.

Right, but this is in a thread. It’s not on the main event loop, so should it not affect the app; rather the apparent responsiveness of the app? (I’m in Theory Land here. I’m asking the tough questions.)

Well if it’s threaded it may not affect your interface, but familiarize yourself with how the priority math works so that you can tweak it to have minimal effect on operation. I don’t think you could guarantee a reliable timeframe though, since the computer would decide when to calculate the threaded loop.

If you had cared to read carefully what I posted above, you may have got your answer :


Using a thread could be of interest if your UI is somewhat demanding and could temporarily halt the execution of the timer. A tight while-wend loop in the main thread could alter the execution of the timer (even stop it during the loop). Placing the poll in the thread will alleviate that issue.

I just tried using a simple system.debuglog in loop with a while-wend using ticks as timer in a thread run event, while the main thread was frozen by a while 1<2/wend. A timer placed on the page was halted, while the thread continued uninterrupted.

If your UI needs heavy lifting, you may want to do your fast polling in the thread.


Putting your poll in a thread is the best way to keep your app responsive and the polling efficient. You are fine with what you did.

[quote=127314:@Garth Hjelte]Is this a limitation of Xojo, or questioned another way, why is that?
[/quote]
Because thats how its always worked & making it any other way is fraught with issues that are akin to those you would have with preemptive multithreading

Removed the unnecessarily rude reply

Something else about Timers: Their Period is not guaranteed. Since they always run on the main loop, they will execute only during idle time, so the Period should be regarded as a “no sooner than” value. If the app’s main thread gets caught up in processing that takes 10 minutes, then the soonest your Timer Action will execute is 10 minutes even if the Period is set to 1.

Which is why you don’t date a timer. Too many unnecessary ‘scare’ episodes…

Well, again, I’m not concerned about timing. I’d like to poll as fast as possible (MIDI and music needs low latency) while keeping the UI as responsive as possible.

Tim Parnells answer seems the most helpful:

Thanks, I’m gonna see how that works. BTW, one thing I was having issues with was do some extensive (well and big graphic being dithered) in the main loop as a UI update was blocking/interfering with a thread. Like Norman seemed to say, threads are stay out of each others way but still everyone has to “line up” for horsepower. it’s not like a thread is a separate computer.

But you could turn it into a separate faceless helper app that preemptively multitasks with your main app or even runs on a different CPU/code, depending on what the OS decides is best.

‘core’, not ‘code’ (I wish posts were editable)

The experience I have with an operation that steals all processing power in the main thread showed a thread with priority 5 to execute flawlessly.

Here is the code I used in a button over the window. The while wend takes all resources, more than a dithering operation. Everything is frozen until I hit spacebar.

Sub Action() Thread1.run while 1<2 if Keyboard.AsyncKeyDown(&h31) then quit wend End Sub

Here is the code in Thread1.Run :

Sub Run() system.DebugLog str(me.Priority) static old as double = microseconds for i as integer = 0 to 100 system.DebugLog format(Microseconds-old,"##.##") old = microseconds next End Sub

The time between loops is between 0.31 and 0.51 Microsecond, while the main thread is completely busy.

Amazingly enough, the same loop in the main thread without any other operation running (no thread) reports very steady response time between 0.46 and 0.48 Microsecond. Seems the thread can be somewhat faster than the main loop.

I know music cannot accommodate any lag, but given these results, I do not see how a helper app could be faster.

This confirms what I told you before : from what I read, and from the results I freshly got, you should be fine with your present code.

is this on Mac or Windows?

TimerMBS has a higher resolution on Windows as low as 1 ms while normal Xojo timer comes to about 60ms.

In general a timer should do better than the thread as it doesn’t keep the app busy all times.

and GUI stuff from threads is not supported well.