イベント ハンドラー コールバックに追加のパラメーターを渡すことはできません。それを呼び出すのはあなたではないためです。タイマーはそうです。それが要点です;-)
ただし、クロージャーを使用して同じ効果を簡単に実現できます。
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");
}
現在、Elapsed ハンドラーは(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");
}
これらすべてのオーバーヘッドについて疑問に思っている場合、それはごくわずかです。ラムダは単なるシンタックス シュガーであり、舞台裏の単純な関数です (イベント用にいくつかの自動デリゲート ラッピングがスローされます)。クロージャは、コンパイラによって生成されたクラスを使用して実装されますが、実際に大量のクロージャがない限り、コードの肥大化に気付くことはありません。
コメントで指摘されているように、コード内の UI 要素にアクセスしているようOnTimerElapsed
です。Windows フォーム タイマーを使用していないため、コードが実行されるため、これを行うと例外が発生する可能性が高くなります。タイマーがイベントを発生させたときにたまたま実行されていたスレッド。Windows の UI コントロールは、それらを作成したスレッドからのみアクセスする必要があります。
手動で修正するためにいじることができますが、プロパティthis.Invoke
を介してタイマーがイベントを適切なスレッドにマーシャリングする方が簡単です:SynchronizingObject
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;
}