21

How to pass parameters to the function called by ElapsedEventHandler?

My code:

private static void InitTimer(int Index)
{
    keepAlive[Index] = new Timer();
    keepAlive[Index].Interval = 3000;
    keepAlive[Index].Elapsed += new ElapsedEventHandler(keepAlive_Elapsed[, Index]);
    keepAlive[Index].Start();
}

public static void keepAlive_Elapsed(object sender, EventArgs e[, int Index])
{

    PacketWriter writer = new PacketWriter();
    writer.AppendString("KEEPALIVE|.\\");
    ServerSocket.Send(writer.getWorkspace(), Index);
    ServerSocket.DisconnectSocket(Index);
}

What I want to do is between the brackets ([ and ]). But just doing it like that obviously doesn't work...

lesderid
  • 3,388
  • 8
  • 39
  • 65
  • 1
    (It's funny to come back to old questions and see how much you've learned in the past 3 years and how you have evolved. This is one of the reasons I love this site.) – lesderid May 15 '13 at 15:53

1 Answers1

51

You can't do this within the method itself - you have to make your event handler aware of its context, effectively. The simplest way of doing this is with a lambda expression or anonymous method:

private static void InitTimer(int Index)
{
    keepAlive[Index] = new Timer();
    keepAlive[Index].Interval = 3000;
    keepAlive[Index].Elapsed += delegate { KeepAliveElapsed(Index); };
    keepAlive[Index].Start();
}

public static void KeepAliveElapsed(int Index)
{    
    PacketWriter writer = new PacketWriter();
    writer.AppendString("KEEPALIVE|.\\");
    ServerSocket.Send(writer.getWorkspace(), Index);
    ServerSocket.DisconnectSocket(Index);
}

Here, the anonymous method (the bit with the delegate keyword) has created a delegate which knows about the Index parameter to InitTimer. It just calls the KeepAliveElapsed method. I've used the anonymous method syntax because you didn't need the sender or event args; if you did need them I'd probably use a lambda expression instead, e.g.

private static void InitTimer(int Index)
{
    keepAlive[Index] = new Timer();
    keepAlive[Index].Interval = 3000;
    keepAlive[Index].Elapsed += (sender, args) => KeepAliveElapsed(sender, Index);
    keepAlive[Index].Start();
}

public static void KeepAliveElapsed(object sender, int Index)
{    
    PacketWriter writer = new PacketWriter();
    writer.AppendString("KEEPALIVE|.\\" + sender);
    ServerSocket.Send(writer.getWorkspace(), Index);
    ServerSocket.DisconnectSocket(Index);
}

(Note that conventionally the Index parameter should be called index, btw.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I have trouble understanding this. Doesn't the Elapsed event expect a ElapsedEventHandler delegate? – SWeko Jun 22 '10 at 15:23
  • 1
    @lesderid: Parameter names are conventionally in camelCase rather than PascalCase. – Jon Skeet Jun 22 '10 at 15:26
  • @SWeko: Yes, and we're creating an ElapsedEventHandler, either with an anonymous method or with a lambda expression. That delegate happens to call `KeepAliveElapsed` but that doesn't have to have the same signature at all. – Jon Skeet Jun 22 '10 at 15:27
  • Missed that. So we are basically doing `timer.Elapsed +=new ElapsedEventHandler((sender, args) => KeepAliveElapsed(index); );` – SWeko Jun 22 '10 at 15:41
  • @SWeko: Yes, although it would be pretty odd to have the "new EventHandler" part when using a lambda expression. – Jon Skeet Jun 22 '10 at 16:19
  • 1
    @amaranth: If you're sorry, you know it's inappropriate to add a comment try to draw attention to another question. I'm not going to reward that behaviour by answering your question. Please do not do this in future. – Jon Skeet Aug 24 '17 at 07:12
  • @JonSkeet I understood. Sorry. I have a unclear error – amaranth Aug 24 '17 at 07:24