JMK
JMK

Reputation: 28059

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

Upvotes: 58

Views: 76740

Answers (7)

Michael Brown
Michael Brown

Reputation: 1

Why not just use a Timer and an ElapsedEventHandler?

namespace TimerEventHandler
{
    class Program
    {
        private static Timer myEventTimer;

        static void Main(string[] args)
        {
            // 5 second timer multiply 1000 milliseconds by the time
            //e.g. new Timer(60 * 1000 * 10) = 10 minutes
            myEventTimer = new Timer(5 * 1000 * 1);
            myEventTimer.Enabled = true;
            myEventTimer.Elapsed += new ElapsedEventHandler(TimerSchedule_Elapsed);

            Console.WriteLine("Timer started!");

            // make a thread and wait forever just so console does not go away
            Thread.Sleep(Timeout.Infinite);
        }

        private static void TimerSchedule_Elapsed(object sender, ElapsedEventArgs e)
        {
            // do something
            Console.WriteLine("Timer elapsed!");
        }
    }
}

Upvotes: -1

lenny
lenny

Reputation: 784

I wrote this simple class to handle this:

using System;
using System.Timers;

namespace MyProject.Helpers
{
    public class MyTimer
    {
        private volatile Timer _timer = new Timer();
        private volatile bool _requestStop = false;
        private MyElapsedEventHandler _eventHander;
        private MyElapsedEventHandlerWithParam _eventHandlerWithParam;
        private object _param;

        public MyTimer(int interval, MyElapsedEventHandler elapsedEventHandler, bool autoReset = false)
        {
            _timer.Interval = interval;
            _timer.Elapsed += ElapsedWrapper;
            _timer.AutoReset = autoReset;

            _eventHander = elapsedEventHandler;

            Start();
        }

        public MyTimer(int interval, MyElapsedEventHandlerWithParam elapsedEventHandler, object param, bool autoReset = false)
        {
            _timer.Interval = interval;
            _timer.Elapsed += ElapsedWrapperWithParam;
            _timer.AutoReset = autoReset;

            _eventHandlerWithParam = elapsedEventHandler;
            _param = param;

            Start();
        }

        private void ElapsedWrapper(object sender, ElapsedEventArgs e)
        {
            if (!_requestStop && _eventHander != null)
            {
                _eventHander();
            }
        }

        private void ElapsedWrapperWithParam(object sender, ElapsedEventArgs e)
        {
            if (!_requestStop && _eventHandlerWithParam != null)
            {
                _eventHandlerWithParam(_param);
            }
        }

        public void Stop()
        {
            _requestStop = true;
            _timer.Stop();
        }

        public void Start()
        {
            _requestStop = false;
            _timer.Start();
        }
    }

    public delegate void MyElapsedEventHandlerWithParam(object param);
    public delegate void MyElapsedEventHandler();
}

use it like this:

void Main(string[] args){
    new MyTimer(durationInSeconds * 1000, EventHandler, "some string");
}

void EventHandler(object param){
    doSomethingWithString((string)param);
}

you can also pass the event arguments or any kind of parameters if you edit the delegate (and the call of the event handler in MyTimer class).

Upvotes: 0

Mahendra
Mahendra

Reputation: 457

 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)
{
};

Upvotes: 1

Michael Geier
Michael Geier

Reputation: 1843

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.

Upvotes: 35

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236248

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

Upvotes: 2

Matt Burland
Matt Burland

Reputation: 45145

Use a field in the same class to hold whatever string you want and then retrieve it in you elapsed event handler. You'll have to be careful about cross-threading issues however.

Upvotes: 0

JaredPar
JaredPar

Reputation: 754803

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) {
  ...
}

Upvotes: 130

Related Questions