As its already mentioned in the other answers the System.Timers.Timer is fired on non-GUI thread. This wont allow you access the GUI element and would raise cross thread exception. You can use MethodInvoker to access the GUI element in tm_Elapsed
event. Since you have the Timer in Forms and want to access GUI element the other Timer class suits you most i.e System.Windows.Forms.Timer.
Implements a timer that raises an event at user-defined intervals.
This timer is optimized for use in Windows Forms applications and must
be used in a window.
protected void Page_Load(object sender, EventArgs e)
{
System.Windows.Forms.Timer tm = new System.Windows.Forms.Timer();
tm.Tick += tm_Tick;
tm.Interval = 1000;
tm.Start();
}
void tm_Tick(object sender, EventArgs e)
{
int lbl = Convert.ToInt32(label1.Text);
label1.Text = (lbl + 1).ToString();
}
Edit based on comments by OP, that he is doing this in web page not win forms as the load event name suggests.
You can use javascript if you do not need anything from server. If you want update the html control and need to do it from server then you can use asp:Timer
Html (.aspx)
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:Timer runat="server" id="UpdateTimer" interval="5000" ontick="UpdateTimer_Tick" />
<asp:UpdatePanel runat="server" id="TimedPanel" updatemode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger controlid="UpdateTimer" eventname="Tick" />
</Triggers>
<ContentTemplate>
<asp:Label id="Label1" runat="server" Text="1" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
Code behind
protected void UpdateTimer_Tick(object sender, EventArgs e)
{
Label1.Text = int.Parse(Label1.Text) + 1;
}