如何将对象传递给计时器事件?

时间:2012-04-02 13:29:07

标签: c# timer

好的,我在.Net 4中使用System.Timers.Timer和C#。

我有我的计时器对象:

var timer = new Timer {Interval = 123};

我的Timer Elapsed事件处理程序指向一个类似的方法:

timer.Elapsed += MyElapsedMethod;

我的方法看起来像这样:

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

我想将一个字符串传递给这个方法,我该怎么做?

由于

7 个答案:

答案 0 :(得分:68)

最简单的方法是将事件处理程序更改为匿名函数。它允许您在声明点传递字符串。

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

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

答案 1 :(得分:15)

如果您希望能够再次取消注册“Elapsed”事件处理程序,则不应在不记住变量的情况下使用委托。

所以另一种解决方案可能是基于Timer创建一个自定义类。只需添加您喜欢的任何成员,并从“Elapsed”事件处理程序的“sender”参数中获取自定义Timer对象:

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

这个策略当然适用于其他事件和类,只要基类没有被密封。

答案 2 :(得分:2)

您可以将字符串保存在某个对象中并在事件处理程序中读取它:

static string _value;

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

更新:通过不同语法的相同代码: timer.Elapsed += (s,e) => Console.WriteLine(_value);

更新:考虑使用System.Threading.Timer而不是

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

您可以在计时器回调中检索状态:

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

    Console.WriteLine(state.Value);
}

答案 3 :(得分:1)

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

答案 4 :(得分:0)

使用同一个类中的字段来保存所需的任何字符串,然后在已用事件处理程序中检索它。但是,您必须小心交叉线程问题。

答案 5 :(得分:0)

我写了这个简单的类来处理这个问题:

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

像这样使用它:

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

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

如果您编辑委托(以及MyTimer类中的事件处理程序的调用),则还可以传递事件参数或任何类型的参数。

答案 6 :(得分:0)

为什么不只使用Timer和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!");
        }
    }
}