Вы не можете передавать дополнительные параметры для обратного вызова обработчика события, потому что вы не тот, кто его вызывает - таймер; что весь смысл ;-)
Но, вы легко можете достичь того же эффекта с крышкой:
private void btnAutoSend_Click(object sender, EventArgs e)
{
timer.Elapsed += (timerSender, timerEvent) => send(timerSender, timerEvent, receiver);
timer.AutoReset = true;
timer.Enabled = true;
}
public void send(object source, System.Timers.ElapsedEventArgs e, string receiver)
{
this.rtbMsg.AppendText("psyche-->" + receiver + ": hello\n");
}
Теперь Прошедшее обработчик действия (timerSender, timerEvent) =>
лямбда, который замыкает над receiver
переменной и вызывает send
вручную с дополнительным параметром всякий раз, когда активируется лямбда.
В вашем конкретном случае вам вообще не нужен отправитель или аргументы, поэтому нет необходимости пересылать их. Код будет следующим:
private void btnAutoSend_Click(object sender, EventArgs e)
{
timer.Elapsed += (s_, e_) => OnTimerElapsed(receiver);
timer.AutoReset = true;
timer.Enabled = true;
}
private void OnTimerElapsed(string receiver)
{
this.rtbMsg.AppendText("psyche-->" + receiver + ": hello\n");
}
Если вы задаетесь вопросом о накладных расходах всего этого, это довольно минимально. Lambdas - это просто синтаксический сахар и являются простыми функциями за кулисами (с некоторой автоматической упаковкой делегатов, добавленной для материала события). Закрытие выполняется с использованием классов, генерируемых компилятором, но вы не заметите раздувания кода, если у вас действительно есть тон из них.
Как указано в комментариях, вы, кажется, обращаетесь к элементу пользовательского интерфейса в коде OnTimerElapsed
- поскольку вы не используете таймер Windows Forms, есть хорошие шансы, что вы получите исключение, сделав это, поскольку код будет запускаться во всех потоках, которые таймер запускает, когда он запускает событие. Элементы управления пользовательского интерфейса в Windows должны иметь доступ к только из потока, который их создал.
Вы могли бы возиться с this.Invoke
, чтобы исправить это вручную, но это легче иметь таймер Маршаллизация событие правой резьбой для вас через SynchronizingObject
property:
private void btnAutoSend_Click(object sender, EventArgs e)
{
timer.SynchronizingObject = this; // Assumes `this` implements ISynchronizeInvoke
timer.Elapsed += (s_, e_) => OnTimerElapsed(receiver);
timer.AutoReset = true;
timer.Enabled = true;
}
Наконец, движимый другой комментарий, вот еще один способ, которым вы могли бы хранить ссылку на закрытии, так что вы можете отказаться от события позже:
private void btnAutoSend_Click(object sender, EventArgs e)
{
timer.SynchronizingObject = this; // Assumes `this` implements ISynchronizeInvoke
ElapsedEventHandler onElapsed;
onElapsed = (s_, e_) => {
timer.Elapsed -= onElapsed; // Clean up after firing
OnTimerElapsed(receiver);
};
timer.Elapsed += onElapsed;
timer.AutoReset = true;
timer.Enabled = true;
}
Ну, вы можете использовать 'System.Windows.Forms.Timer' если добавить ссылку на библиотеку. – annonymously
[как передать параметр отправителя на system.timers.timer] (http://stackoverflow.com/questions/6368399/how-to-pass-the-the-sender-parameter-to-the-system -timers-timer) – Damith
Вам не следует использовать System.Windows.Timer с любыми компонентами пользовательского интерфейса (например, rtbMsg.AppendText, скорее всего, имеет доступ к некоторому виду управления окнами), System.Timer.Elapsed вызывается в потоке без интерфейса и будет вызывать исключение в большинстве случаев. Если вы не WinForms и WPF, то вы захотите использовать DispatchTimer. Если вы можете уточнить, какую ошибку вы получаете, кто-то может предложить более точный совет. –