Ping已完成事件处理程序无法正常工作

时间:2015-11-24 14:58:43

标签: c#

当我在命令行中执行此代码时,它工作正常:

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();
     }
}

此代码有什么问题?

1 个答案:

答案 0 :(得分:0)

方法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返回值,那么你可以通过(标记方法的标记,await仍然使用async):

var result = await p.SendAsync(...);