3

I am trying to pass some data from one event handler to another, but i am a little bit stuck. In the following code, I have two events:

  • one is the "timer elapsed" event
  • the second is the "Ping Completed" event which is raised from the "timer elapsed" event

In the "Ping Completed" event, I need to access one variable from the timer elapsed event. How can I do that ?

void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
   for (int i = 0; i < this.View.Rows.Count; i++)
   {
      this.IP = View.Rows[i].Cells[2].Value.ToString();
      PingOptions Options = new PingOptions(10, true);
      Ping thisPing = new Ping();
      thisPing.SendAsync(IPAddress.Parse(IP), 100, new byte[0], Options);
      thisPing.PingCompleted += new PingCompletedEventHandler(thisPing_PingCompleted);                    
    }
}

void thisPing_PingCompleted(object sender, PingCompletedEventArgs e)
{
    //i need to accsess the "int i" of the above loop Here
}
Donut
  • 110,061
  • 20
  • 134
  • 146

2 Answers2

3

This is exactly what the userToken parameter of the SendAsync method should be used for

PingOptions options = new PingOptions(10, true);
Ping thisPing = new Ping();
thisPing.SendAsync(IPAddress.Parse(IP), 100, new byte[0], options, i);
thisPing.PingCompleted += new PingCompletedEventHandler(thisPing_PingCompleted); 
...

void thisPing_PingCompleted(object sender, PingCompletedEventArgs e)
{
    var index = (int)e.UserState;
    ...
}

Also, given you are using SendAsync you don't need to create an instance of Ping per iteration. You can simply re-use the existing instance, each call to SendAsync will send off the ping in a different thread and then callback to your event handler i.e.

void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{            
    PingOptions Options = new PingOptions(10, true);
    Ping thisPing = new Ping();
    thisPing.PingCompleted += new PingCompletedEventHandler(thisPing_PingCompleted);  
    // send pings asynchronously
    for (int i = 0; i < this.View.Rows.Count; i++)
    {
        var ip = View.Rows[i].Cells[2].Value.ToString();
        thisPing.SendAsync(ip, 100, new byte[0], options, i);                  
    }
}
James
  • 80,725
  • 18
  • 167
  • 237
1

You could derive from the Ping and then pass your argument in the Pings constructor. Then you have all the freedom to change the behavior of the event and you can alter it to your needs.

I made a simple class from which you can begin with

class ExtendedPing : Ping
{
    public delegate void ExtendedPing_Completed(object sender, PingCompletedEventArgs e, int identifier);
    public event ExtendedPing_Completed On_ExtendedPing_Completed;

    private int _i = 0;

    public ExtendedPing(int i)
    {
        _i = i;
        base.PingCompleted += ExtendedPing_PingCompleted;
    }

    void ExtendedPing_PingCompleted(object sender, PingCompletedEventArgs e)
    {
        if (On_ExtendedPing_Completed != null) 
        {
            On_ExtendedPing_Completed(sender, e, _i);
        }
    }
}

Feel free to read https://msdn.microsoft.com/en-gb/library/ms228387(v=VS.90).aspx a little bit more about inheritence.

Bongo
  • 2,933
  • 5
  • 36
  • 67
  • Seems a bit over-engineered, an anonymous delegate would suffice if for whatever reason you didn't want to use the `userToken` overload. – James Jul 24 '15 at 15:28
  • @James Until I read your answer I wasn't aware of the user token. I would also go with the token for a simple integer. I am not a big fan of anonymous delegates because (and this is only my subjective opinion) it makes the code for me less readable if overused. Correct me if I am wrong here but if you want to unsubscribe the event you will have to keep record of the delegates around. – Bongo Jul 24 '15 at 15:38
  • @Bongo that is correct, however, depending on the lifespan of the object unhooking it may not be much of a requirement. Even at that, you can use a variable to name your delegate to make it much clearer as to what you are doing e.g. `var pingComplete = delegate(...) { ... }` – James Jul 24 '15 at 15:51