Как передать объект в событие таймера? - PullRequest
28 голосов
/ 02 апреля 2012

Хорошо, поэтому я использую System.Timers.Timer в .Net 4 с C #.

У меня есть объект таймера, например:

var timer = new Timer {Interval = 123};

Мой обработчик события Timer Elapsed указывает на метод, подобный так:

timer.Elapsed += MyElapsedMethod;

И мой метод выглядит так:

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

Я хочу передать строку в этот метод, как мне это сделать?

Спасибо

Ответы [ 6 ]

70 голосов
/ 02 апреля 2012

Самый простой способ сделать это - преобразовать обработчик событий в анонимную функцию. Позволяет передать строку в точке объявления.

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

static void MyElapsedMethod(object sender, ElapsedEventArgs e, string theString) {
  ...
}
15 голосов
/ 21 февраля 2015

Если вы хотите снова отменить регистрацию обработчика событий Elapsed, вам не следует использовать делегат, не запоминая его в переменной.

Таким образом, другим решением может быть создание пользовательского класса на основе Timer. Просто добавьте любые элементы, которые вам нравятся, и получите свой собственный объект 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 голосов
/ 02 апреля 2012

Вы можете сохранить строку в некотором объекте и прочитать ее в обработчике событий:

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);
}
1 голос
/ 02 июля 2017
 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)
{
};
0 голосов
/ 05 апреля 2019

Я написал этот простой класс для обработки этого:

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

0 голосов
/ 02 апреля 2012

Используйте поле в том же классе для хранения любой строки, которую вы хотите, а затем извлекайте ее в обработчике прошедшего события.Однако вы должны быть осторожны с проблемами многопоточности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...