The "My timer" event crashes because events are called on another thread
I get the error "Invalid cross-stream operation: control 'label1' is accessible from a thread other than the thread in which it was created." when i run this code:
using System;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Timers;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
System.Timers.Timer T = new System.Timers.Timer();
public Form1()
{
InitializeComponent();
T.Elapsed += new ElapsedEventHandler(T_Elapsed);
T.Start();
}
void T_Elapsed(object sender, ElapsedEventArgs e)
{
label1.Text = "This will not work";
}
}
}
I thought the events are running on the same thread they were fired on.
source to share
We have 3 timer classes in NET (Timers.Timer, Threading.Timer and Windows.Forms.Timer), but only Windows.Forms has a Tick event.
In normal use (i.e. dragged onto a form at design time or generated in some form code) the event is triggered on the main thread and your problem shouldn't occur.
So most likely you are creating a Timer object on a different thread, you should probably change your question to show us how / where you create it and tell us if it is for a different Thread.
source to share
Do you remember using InvokeRequired ? This will allow you to update the UI element on the UI thread from the Timer thread.
source to share
I am assuming you are talking about a WinForms application.
When trying to update a Form element (which lives on the UI thread) from another thread, you need to use Control.Invoke or Control.BeginInvoke . You pass a delegate to the method you want to call (or you pass an anonymous method) and then that delegate is called on the UI thread, not the calling thread.
source to share
Yes, events run on the same thread that called them. It just so happens to System.Timers.Timer
use the ThreadPool
default thread when creating an event Elapsed
. Use the property SynchronizingObject
to have the event handler Elapsed
run on the thread that hosted the target.
public partial class Form1 : Form
{
System.Timers.Timer T = new System.Timers.Timer();
public Form1()
{
InitializeComponent();
T.Elapsed += new ElapsedEventHandler(T_Elapsed);
T.SynchronizingObject = this;
T.Start();
}
void T_Elapsed(object sender, ElapsedEventArgs e)
{
label1.Text = "This will not work";
}
}
source to share