Ping完成的事件处理程序不工作

本文关键字:程序 工作 事件处理 Ping | 更新日期: 2023-09-27 18:24:03

当我在命令行中执行此代码时,它运行良好:

class Program
{
    private static List<Ping> pingers = new List<Ping>();
    private static List<string> value = new List<string>();
    private static int instances = 0;
    private static object @lock = new object();
    private static int result = 0;
    private static int timeOut = 2500;
    private static int ttl = 7;
    public static void Main()
    {
        string baseIP = "192.168.1.";
        Console.WriteLine("Pinging  destinations of D-class in {0}*", baseIP);
        CreatePingers(254);

        PingOptions po = new PingOptions(ttl, true);
        System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
        byte[] data = enc.GetBytes("");
        SpinWait wait = new SpinWait();
        int cnt =1;
        Stopwatch watch = Stopwatch.StartNew();
        foreach (Ping p in pingers)
        {
            lock (@lock)
            {
                instances += 1;
            }
            p.SendAsync(string.Concat(baseIP, cnt.ToString()), timeOut, data, po);
            cnt += 1;
        }
        //while (instances > 0)
        //{
        //    wait.SpinOnce();
        //}
        watch.Stop();
        for (int i = 0; i < value.Count; i++)
        {
            Console.WriteLine(value[i]);
        }
        DestroyPingers();
        Console.WriteLine("Finished in {0}. Found {1} active IP-addresses.", watch.Elapsed.ToString(), result);
        Console.ReadKey();
    }
    public static void Ping_completed(object s, PingCompletedEventArgs e)
    {
        lock (@lock)
        {
            instances -= 1;
        }
        if (e.Reply.Status == IPStatus.Success)
        {
           string sa = string.Concat("Active IP: ", e.Reply.Address.ToString());
           value.Add(sa);
          //Console.WriteLine(sa);
            String diachiip = e.Reply.Address.ToString();
            result += 1;
        }
        else
        {
            //Console.WriteLine(String.Concat("Non-active IP: ", e.Reply.Address.ToString()))
        }
    }

    private static void CreatePingers(int cnt)
    {
        for (int i = 1; i <= cnt; i++)
        {
            Ping p = new Ping();
            p.PingCompleted += Ping_completed;
            pingers.Add(p);
        }
    }
    private static void DestroyPingers()
    {
        foreach (Ping p in pingers)
        {
            p.PingCompleted -= Ping_completed;
            p.Dispose();
        }
        pingers.Clear();
    }
}

但当我从它转换为窗口形式时,它不起作用。我不知道为什么,我试过很多不同的方法。。。

代码在这里:

public partial class Form1 : Form
{
    public static List<Ping> pingers = new List<Ping>();
    public static List<string> value = new List<string>();
    public static int instances = 0;
    public static object @lock = new object();
    public static int result = 0;
    public int timeout = 2500;
    public static int ttl = 7;
    public Form1()
    {
        InitializeComponent();
    }
    public void btnscan_Click(object sender, EventArgs e)
    {
        string baseIP = "192.168.1.";
        //int kt = Int32.Parse(txtkt.Text);
        //int start = Int32.Parse(txtstart.Text);
        CreatePingers(254);
        PingOptions po = new PingOptions(ttl, true);
        System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
        byte[] data = enc.GetBytes("");
        int cnt = 1;
        Stopwatch watch = Stopwatch.StartNew();
        foreach (Ping p in pingers)
        {
            lock (@lock)
            {
                instances += 1;
            }
            p.SendAsync(string.Concat(baseIP, cnt.ToString()), timeout, data, po);
            cnt += 1;        
        }
        watch.Stop();
        //Result alway return 0
        lst1.Items.Add(result.ToString());
        lst1.Items.Add(value.Count.ToString());
        for (int i = 0; i < value.Count; i++)
        {
            lst1.Items.Add(value[i]);
            lst1.Items.Add("'n");
        }
        DestroyPingers();
        string a = "Finished in " + watch.Elapsed.ToString() + ". Found " + result + " active IP-addresses.";
        lst1.Items.Add(a);
    }

    public static void CreatePingers(int kt)
    {
        for (int start = 1; start <= kt; start++)
        {
            // class System.Net.NetworkInformation.Ping
            Ping p = new Ping();
            p.PingCompleted += Ping_completed();
            pingers.Add(p);
        }
    }
     public static PingCompletedEventHandler Ping_completed()
    {
         PingCompletedEventHandler a = new PingCompletedEventHandler(abc);
         return a;
    }
    static void abc(object s, PingCompletedEventArgs e)
     {
         value.Add("abc");
         lock (@lock)
         {
             instances -= 1;
         }
         if (e.Reply.Status == IPStatus.Success)
         {
             string abcd = string.Concat("Active IP: ", e.Reply.Address.ToString());
             value.Add(abcd);
             result += 1;
         }
     }
     public static void DestroyPingers()
     {
         foreach (Ping p in pingers)
         {
             p.PingCompleted -= Ping_completed();
             p.Dispose();
         }
         pingers.Clear();
     }
}

这个代码出了什么问题?

Ping完成的事件处理程序不工作

方法SendAsync返回0,因为您没有等待它完成。您缺少awaitasync(请参阅msdn):

async void btnscan_Click(object sender, EventArgs e)
{
    ...
    await p.SendAsync(string.Concat(baseIP, cnt.ToString()), timeout, data, 
    ...
}

SpinWait正在编写代码以便在控制台应用程序中工作。在winforms中,您不应该在UI线程中使用SpinWait(也不应该使用Sleep)。您可以创建另一个线程(例如使用Task),然后可以从控制台应用程序1对1复制/粘贴代码。但是,每次访问UI控件时都需要使用Invoke

async/await确实更好。。如果它能起作用(我从方法名称得出结论,我不知道方法做什么,也不知道如何使用它)。

也许我错过了一件事,如果SendAsync返回值,那么你可以通过(在async仍然使用await的情况下标记方法的要求)获得它:

var result = await p.SendAsync(...);
相关文章: