How do I pass an object into a timer event?

Ok so I am using System.Timers.Timer in .Net 4 with C#.

I have my timer object like so:

var timer = new Timer {Interval = 123};

I have my Timer Elapsed event handler pointed at a method like so:

timer.Elapsed += MyElapsedMethod;

And my method looks like this:

static void MyElapsedMethod(object sender, ElapsedEventArgs e)
{
    Console.WriteLine("Foo Bar");
}

I want to pass a string into this method, how do I do this?

Thanks


Solution 1:

The easiest way to do this is to change the event handler into an anonymous function. It allows you to pass the string at the point of declaration.

string theString = ...;
timer.Elapsed += (sender, e) => MyElapsedMethod(sender, e, theString);

static void MyElapsedMethod(object sender, ElapsedEventArgs e, string theString) {
  ...
}

Solution 2:

If you want to be able to unregister your "Elapsed" event handler again, you shouldn't use a delegate without remembering it in a variable.

So another solution could be to create a custom class based on Timer. Just add whatever members you like and get your custom Timer object back from the "sender" argument of the "Elapsed" event handler:

class CustomTimer : System.Timers.Timer
{
    public string Data;
}

private void StartTimer()
{
    var timer = new CustomTimer
    {
        Interval = 3000,
        Data = "Foo Bar"
    };

    timer.Elapsed += timer_Elapsed;
    timer.Start();
}

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    string data = ((CustomTimer)sender).Data;
}

This strategy of course works for other events and classes too, as long as the base class is not sealed.

Solution 3:

You can save string in some object and read it in event handler:

static string _value;

static void MyElapsedMethod(object sender, ElapsedEventArgs e)
{
    Console.WriteLine(_value);
}

UPDATE: same code via different syntax: timer.Elapsed += (s,e) => Console.WriteLine(_value);

UPDATE: Consider also using System.Threading.Timer instead

State state = new State();
Timer timer = new Timer(OnTimer, state, 0, 123);
state.Value = "FooBar"; // change state object

You can retrieve state in timer callback:

static void OnTimer(object obj)
{
    State state = obj as State;
    if (state == null)
        return;        

    Console.WriteLine(state.Value);
}

Solution 4:

 Timer aTimer = new Timer(300);
                aTimer.Elapsed += delegate { PublishGPSData(channel, locationViewModel); };
                // Hook up the Elapsed event for the timer. 
                aTimer.AutoReset = true;
                aTimer.Enabled = true;
private void PublishGPSData(IModel channel, LocationViewModel locationViewModel)
{
};