向事件处理程序传递额外的参数?

3

我想将一些数据从一个事件处理程序传递到另一个,但我有点困惑。

在下面的代码中,我有两个事件:

  • 一个是“计时器已过去”事件
  • 第二个是从“计时器已过去”事件引发的“Ping完成”事件

在“Ping完成”事件中,我需要访问来自计时器已过去事件的一个变量。我该怎么做?

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
}

您可能还想尝试 var resp = await thisPing.SendPingAsync(...) - EZI
2个回答

3
这正是SendAsync方法的userToken参数应用的场景。这个参数可以帮助你跟踪异步操作,确保在操作完成后正确地处理结果。
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;
    ...
}

此外,由于您正在使用SendAsync,因此您不需要为每个迭代创建一个Ping实例。您可以简单地重复使用现有实例,每次调用SendAsync都会在不同的线程中发送ping,然后回调到您的事件处理程序,即:
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);                  
    }
}

酷,我之前不知道有这个用户令牌。 - Bongo

1
你可以从Ping中派生,然后将参数传递给Ping的构造函数。然后您就可以自由地更改事件的行为,并将其修改为符合您的需求。
我制作了一个简单的类,供您开始使用。
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);
        }
    }
}

随意阅读https://msdn.microsoft.com/en-gb/library/ms228387(v=VS.90).aspx,了解更多关于继承的内容。


看起来有点过度设计了,如果由于某种原因您不想使用userToken重载,则匿名委托就足够了。 - James
@James 在看到你的回答之前,我并不知道用户令牌。我也会选择使用令牌来表示一个简单的整数。我不是匿名委托的忠实粉丝,因为(这只是我的主观意见)如果过度使用,它会使代码变得更难读。如果我错了,请纠正我,但如果您想取消订阅事件,则必须记录委托。 - Bongo
@Bongo 这是正确的,但是根据对象的生命周期来切断它可能并不是很必要。即便如此,你仍然可以使用一个变量来命名你的委托,以使你所做的更加清晰明了,例如var pingComplete = delegate(...) { ... } - James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接