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.

+2


source to share


8 answers


You may be using the wrong timer. Try a WinForms timer, it runs on a GUI thread, so you don't have to do Invoke



+2


source


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.

+3


source


While the "Accepted" answer is technically correct (in doing so it will fix the problem), it doesn't answer the question.

ANSWER should use

void T_Elapsed(object sender, ElapsedEventArgs e)
{
    this.BeginInvoke(new MethodInvoker(delegate(){
        label1.Text = "This will work";
    }));
}

      

http://jaysonknight.com/blog/archive/2007/02/14/using-anonymous-methods-for-control-invoke-control-begininvoke.aspx

+3


source


Do you remember using InvokeRequired ? This will allow you to update the UI element on the UI thread from the Timer thread.

+1


source


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.

+1


source


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";
  }
}

      

+1


source


If you are doing this asynchronously (which sounds like you), make sure you catch the exceptions in your event handler or callback. If a background thread throws an exception, it will crash the application. This is the most common reason I've seen this behavior.

0


source


I am not a winform developer. But I heard something you read in the Timer class. I think you can set these properties and check.

T.Interval = 5000; //in Mili Seconds
T.Enabled = true;

      

-1


source







All Articles