您不能將額外的參數傳遞給事件處理函數回調函數,因爲您不是那個調用它的函數 - Timer是;這是整點;-)
但是,你可以輕鬆地完成與結束具有同等效力:
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
每當lambda被觸發時手動使用額外的參數。
在您的具體情況下,您根本不需要發件人或參數,因此無需轉發它們。代碼變爲:
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
代碼中的UI元素 - 因爲您沒有使用Windows窗體計時器,所以很有可能會因爲這樣做而收到異常代碼將運行在定時器碰巧運行時的任何線程上 - 並且Windows 中的UI控件必須從創建它們的線程訪問僅。
你可以更動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
相關[如何將sender參數傳遞給system.timers.timer](http://stackoverflow.com/questions/6368399/how-to-pass-the-the-sender-parameter-to-the-system -timers-timer) – Damith
你不應該在任何UI組件中使用System.Windows.Timer(例如rtbMsg.AppendText可能訪問某種類型的Windows控件),System.Timer.Elapsed在非UI線程上被調用並且會導致在大多數情況下是例外。如果你不是WinForms並且是WPF,那麼你會想要使用DispatchTimer。如果你能澄清你收到的錯誤,有人可能會提供更準確的建議。 –