2012-06-19 18 views
15

Tôi đang sử dụng system.Timers.Timer để tạo bộ hẹn giờ.cách sử dụng Bộ hẹn giờ trong 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"); 
} 

Các nhận trong gửi chức năng là một tham số mà tôi cần phải thiết lập khi hàm được sử dụng, nhưng khi tôi thêm một tham số trong send chức năng, như:

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

Sau đó, nó ném một lỗi. Sau khi tôi kiểm tra MSDN, nó cho biết ElapsedEventArgs chỉ có sẵn cho các chức năng này sẽ không sản xuất dữ liệu.

Làm cách nào để giải quyết vấn đề này? Chương trình của tôi không phải là windows.Form, vì vậy tôi không thể sử dụng System.Windows.Forms.Timer.

+0

Vâng, bạn có thể dùng lệnh 'System.Windows.Forms.Timer' nếu bạn thêm một tham chiếu đến thư viện. – annonymously

+0

có liên quan [cách chuyển tham số người gửi đến system.timers.timer] (http://stackoverflow.com/questions/6368399/how-to-pass-the-the-sender-parameter-to-the-system -imers-timer) – Damith

+0

Bạn không nên sử dụng System.Windows.Timer với bất kỳ thành phần giao diện người dùng nào (ví dụ: rtbMsg.AppendText có khả năng truy cập một số loại điều khiển cửa sổ), System.Timer.Elapsed được gọi trên một chuỗi giao diện người dùng không và sẽ gây ra một ngoại lệ trong hầu hết các trường hợp. Nếu bạn không phải là WinForms và là WPF, thì bạn sẽ muốn sử dụng DispatchTimer. Nếu bạn có thể làm rõ những gì bạn đang nhận được lỗi, ai đó có thể cung cấp lời khuyên chính xác hơn. –

Trả lời

19

Bạn không thể chuyển các tham số bổ sung vào trình xử lý sự kiện của trình xử lý sự kiện, vì bạn không phải là người gọi nó - Timer là; đó là toàn bộ điểm ;-)

Tuy nhiên, bạn có thể dễ dàng đạt được tác dụng tương tự với một kết thúc:

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

Bây giờ xử lý đã qua là hành động (timerSender, timerEvent) => lambda, mà đóng cửa trong vòng receiver biến và kêu gọi send bằng tay với tham số phụ bất cứ khi nào lambda được kích hoạt.

Trong trường hợp cụ thể của bạn, bạn không cần người gửi hoặc đối số nào cả, do đó không cần chuyển tiếp chúng. Mã trở thành:

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

Nếu bạn đang băn khoăn về chi phí của tất cả điều này, nó khá là tối thiểu. Lambdas chỉ là cú pháp cú pháp và là các hàm đơn giản đằng sau hậu trường (với một số gói ủy nhiệm tự động được ném vào cho các sự kiện). Các bao đóng được thực hiện bằng cách sử dụng các lớp do trình biên dịch tạo ra, nhưng bạn sẽ không nhận thấy bất kỳ mã nào bị sưng lên trừ khi bạn thực sự có tấn của chúng.

Như đã nêu trong phần nhận xét, có vẻ như bạn đang truy cập phần tử giao diện người dùng trong mã OnTimerElapsed - vì bạn không sử dụng bộ hẹn giờ Windows Forms, bạn sẽ có ngoại lệ khi thực hiện việc này vì mã sẽ chạy trên bất kỳ chuỗi nào mà bộ hẹn giờ sẽ chạy khi nó kích hoạt sự kiện - và các điều khiển giao diện người dùng trong Windows phải được truy cập chỉ từ chuỗi đã tạo chúng.

Bạn có thể lộn xộn xung quanh với this.Invoke để sửa chữa nó bằng tay, nhưng nó dễ dàng hơn để có bộ đếm thời gian marshall các sự kiện để các chủ đề phù hợp với bạn thông qua 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; 
} 

Cuối cùng, thúc đẩy bởi một nhận xét, đây là một cách khác để bạn có thể lưu trữ tham chiếu đến việc đóng để bạn có thể hủy đăng ký khỏi sự kiện sau:

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

Tại sao phải khởi động bộ hẹn giờ trước khi đặt tự động và gọi lại? timer.Enabled = true phải là điều cuối cùng bạn làm – nbrooks

+0

@nbrooks: Tốt, tôi chỉ đang sao chép mã của OP. Tôi sẽ chỉnh sửa điều đó trong – Cameron

+0

@nbrooks giống như timer.Start()? – Damith

3

Bạn không thể chuyển các tham số bổ sung cho trình xử lý sự kiện như vậy.

Lưu giá trị của bạn vào một biến cấp đối tượng để có thể truy cập nó trong trình xử lý sự kiện.

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

    } 
}