Reputation: 450
I'm trying to make System.Windows.Forms.Timer to work after animation.
private Timer timer1 = new Timer();
protected override void OnLoad(EventArgs e)
{
timer1.Interval = 25;
timer1.Tick += timer1_Tick;
tempX = this.Location.X;
new Animator2D(new Path2D(-300, 23, this.Location.Y, this.Location.Y, 1500, AnimationFunctions.ExponentialEaseOut))
.Play(this, Animator2D.KnownProperties.Location, new SafeInvoker((() =>
{
timer1.Enabled = true;
})));
base.OnLoad(e);
}
I use this method. But it doesn't work
So I changed method like this.
private Timer timer1 = new Timer();
protected override void OnLoad(EventArgs e)
{
timer1.Interval = 25;
timer1.Tick += timer1_Tick;
tempX = this.Location.X;
new Animator2D(new Path2D(-300, 23, this.Location.Y, this.Location.Y, 1500, AnimationFunctions.ExponentialEaseOut))
.Play(this, Animator2D.KnownProperties.Location, new SafeInvoker((() =>
{
Invoke(new Action(() => timer1.Enabled = true));
})));
base.OnLoad(e);
}
It work.
I don't know the difference between the methods.
Through the debugger, timer1's Enabled value is changed to True even when using the first method.
I wonder why this happens.
Upvotes: 1
Views: 389
Reputation: 13676
Explanation:
This happens because method Invoke
runs the code on the same thread context as control's underlying thread (which is the UI Thread in our case). Think of context as the current state of the thread and how it views memory at a specific time.
So when we don't use Invoke
it is likely that the code runs on a different thread which also contains timer1
. The code sets Enabled
property to true
there in that specific thread's context. Think of it as though you have two Timers instead of one - one in say thread A
and another one in thread B
.
Conclusion:
In order to avoid this mess we should always use Invoke
when we need to update fields or properties in our Form while working in multi-threaded environment.
Upvotes: 1