2012-06-19 4 views
15

Я использую system.Timers.Timer для создания таймера.Как использовать Таймер в C#

public System.Timers.Timer timer = new System.Timers.Timer(200); 
private void btnAutoSend_Click(object sender, EventArgs e) 
{ 
    timer.Enabled = true; 
    timer.Elapsed += new System.Timers.ElapsedEventHandler(send); 
    timer.AutoReset = true; 
} 

public void send(object source, System.Timers.ElapsedEventArgs e) 
{ 
    this.rtbMsg.AppendText("psyche-->" + receiver + ": hello\n"); 
} 

приемник в функции отправки является параметром, который мне нужно установить, когда функция используется, но когда я добавить параметр в функции отправки, как:

public void send(object source, System.Timers.ElapsedEventArgs e,string receiver) 

Тогда он выдает ошибку. После того, как я проверил MSDN, он сказал, что ElapsedEventArgs доступен только для этой функции, которая не будет производить данные.

Как я могу решить эту проблему? Моя программа - это не windows.Form, поэтому я не могу использовать System.Windows.Forms.Timer.

+0

Ну, вы можете использовать 'System.Windows.Forms.Timer' если добавить ссылку на библиотеку. – annonymously

+0

[как передать параметр отправителя на system.timers.timer] (http://stackoverflow.com/questions/6368399/how-to-pass-the-the-sender-parameter-to-the-system -timers-timer) – Damith

+0

Вам не следует использовать System.Windows.Timer с любыми компонентами пользовательского интерфейса (например, rtbMsg.AppendText, скорее всего, имеет доступ к некоторому виду управления окнами), System.Timer.Elapsed вызывается в потоке без интерфейса и будет вызывать исключение в большинстве случаев. Если вы не WinForms и WPF, то вы захотите использовать DispatchTimer. Если вы можете уточнить, какую ошибку вы получаете, кто-то может предложить более точный совет. –

ответ

19

Вы не можете передавать дополнительные параметры для обратного вызова обработчика события, потому что вы не тот, кто его вызывает - таймер; что весь смысл ;-)

Но, вы легко можете достичь того же эффекта с крышкой:

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

Зачем запускать таймер перед установкой автосекретаря и перезваниванием? timer.Enabled = true должно быть последним, что вы делаете – nbrooks

+0

@nbrooks: Хорошо, я просто копировал код OP. Я отредактирую это в – Cameron

+0

. @Nbrooks это то же самое, что и timer.Start()? – Damith

3

You не может передавать дополнительные параметры обработчику событий.

Сохраните свое значение в переменной уровня объекта, чтобы его можно было получить в обработчике событий.

private string receiver; 

public System.Timers.Timer timer = new System.Timers.Timer(200); 
private void btnAutoSend_Click(object sender, EventArgs e) 
{ 
    timer.Enabled = true; 
    receiver = 'your val'; 
    timer.Elapsed += new System.Timers.ElapsedEventHandler(send); 
    timer.AutoReset = true; 
} 

public void send(object source, System.Timers.ElapsedEventArgs e) 
{ 
    this.rtbMsg.AppendText("psyche-->" + receiver + ": hello\n"); 
} 
2
public partial class Form2 : Form 
{ 
    Timer timer = new Timer(); 
    public Form2() 
    { 
     InitializeComponent(); 
     timer.Tick += new EventHandler(timer_Tick); // Every time timer ticks, timer_Tick will be called 
     timer.Interval = (10) * (1000);    // Timer will tick every 10 seconds 
     timer.Start();        // Start the timer 
    } 
    void timer_Tick(object sender, EventArgs e) 
    { 
     //MessageBox.Show("Tick");     // Alert the user 
     var time = DateTime.Now; 
     label1.Text = $"{time.Hour} : {time.Minute} : {time.Seconds} : {time.Milliseconds}"; 
    } 
    private void Form2_Load(object sender, EventArgs e) 
    { 

    } 
} 
Смежные вопросы