I initially meant to post this as comment, but it turned to be too long.
Firstly, your thread structure is a bit confusing to me, the way you described it. Put Debug.WriteLine("OnEvent:" + Thread.CurrentThread.ManagedThreadId)
inside OnEvent
and let us know all thread IDs you see from your debug output.
That said, the rules are:
You should create WinForms'
Timer
object on an STA thread, and the thread should be configured as STA before it starts.This thread may or may not be the main UI thread (where your main form was created), but it still should execute a message loop (with Application.Run) for timer events to fire. There are other ways of pumping messages, but generally you do not control them from .NET code.
You should handle the events sourced by WinForms'
Timer
on the same thread it was created. You can then 'forward' these events to another thread context if you like (using SynchronizationContextSend
orPost
) but I can't think of any reasons for such complexity.
The answer by @Maarten actually suggests the right way of doing it, in my opinion.