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