简体   繁体   中英

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

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

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.

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

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

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM