C# 多个 Ping 启动并重叠它们的结果

C# Multiple Ping start and overlap their Results

我已经创建了一个代码,它将持续测试连接是否可用,并且应该能够更改 IP 并且始终需要 运行 因此它可以在连接是否可用时显示在通知中可用与否。我可以毫无错误地执行它,但是当我再次单击发送按钮时,它会启动另一个 ping,该 ping 也会将结果放在彼此重叠的标签框中。我愿意接受所有解决此问题的建议。

    private async void Button1_Click(object sender, EventArgs e) //send button
    {
        int unterbrechung = 0;
        await Task.Delay(12);
        //Erstellen Variablen
        string value = (comboBox1.SelectedItem as dynamic).Value;
        double laufzeit = 0;
        double delayins = 0;
        int delay = 1000;
        int onetimebubble = 1; //Zum verhindern von wieder erscheinen der Warnmeldung
        //Zum verhindern das MiniIcon ein weiterers mal zu ändern.
        int onetimeminired = 0; 
        int onetimeminigreen = 0;
        //Ping Variablen deklarieren und setzen
        Ping pingSender = new Ping();
        PingOptions options = new PingOptions
        {
            DontFragment = true
        };
        pingSender.SendAsyncCancel();
        string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        byte[] buffer = Encoding.ASCII.GetBytes(data);
        int timeout = 120;
        unterbrechung = 1;
        //Ping senden und bei fehler entsprechende meldung anzeigen
        while (unterbrechung == 1)
        {              
            try
            {
                //Ping ausführen und Ausgabe meldung

                PingReply reply = pingSender.Send(value, timeout, buffer, options);
                if (reply.Status == IPStatus.Success)
                {
                    labelOutput.Text = "Address        :" + reply.Address.ToString() + " " + Environment.NewLine +
                                       "Status         :" + reply.Status + " " + Environment.NewLine +
                                       "Laufzeit in s  :" + laufzeit;
                    labelOutput.BackColor = System.Drawing.Color.Green;
                    //Reset der Variable
                    if (onetimeminigreen == 0)
                    {
                        //ändern Symbol + vorheriger test
                        minIcon.Icon = Properties.Resources.Symbol2;
                        onetimeminigreen = 1;
                        onetimeminired = 0;
                    }
                    if (onetimebubble == 0)
                    {
                        onetimebubble = 1;
                    }
                }

            }
            catch(PingException)
            {
                //Reset Laufzeit
                laufzeit = 0;
                //ausgabe fehlermeldung
                labelOutput.Text = "Address        :" + value + " " + Environment.NewLine +
                                   "Status         :Failed" + Environment.NewLine +
                                   "Laufzeit in s  :" + laufzeit;
                labelOutput.BackColor = System.Drawing.Color.Red;
                await Task.Delay(10);
                if (onetimeminired == 0)
                {
                    //ändern Symbol + vorheriger test
                    minIcon.Icon = Properties.Resources.Symbol1;
                    onetimeminigreen = 0;
                    onetimeminired = 1;
                }
                if (onetimebubble == 1)
                {
                    //ausgabe Warnmeldung + vorheriger test                  
                    minIcon.BalloonTipIcon = ToolTipIcon.Error;
                    minIcon.BalloonTipTitle = "Ping Failed!";
                    minIcon.BalloonTipText = "Sie haben keine verbindung zu ihrem Host";
                    minIcon.ShowBalloonTip(1000);
                    onetimebubble = 0;                     
                }
            }
            //Ausführen delay
            await Task.Delay(delay);
            //erechnen des Delay in sekunden und laufzeit berechnung
            delayins = delay / 1000;
            laufzeit = laufzeit + delayins;
        }


    }

编辑忘记了问题。我如何更改我的程序,如果我再次单击该按钮,它会取消我之前启动的所有其他 ping。 "unterbrechung" 是我试图实现的目标,但失败了。

封装ping 正如 Fildor 建议的那样,我为 Ping 添加了一个新的 class,它只是 returns 结果

    public bool Ping(string ipaddress)
    {
        Ping pingSender = new Ping();
        PingOptions options = new PingOptions
        {
            DontFragment = true
        };
        int timeout = 120;
        pingSender.SendAsyncCancel();
        string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
        byte[] buffer = Encoding.ASCII.GetBytes(data);

        try
        {
            PingReply reply = pingSender.Send(ipaddress, timeout, buffer, options);
            if(reply.Status == IPStatus.Success)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        catch (PingException)
        {
            return false;
        }
    }

方法 PING 和 UI 更改 正如 Fildor 还建议的那样,我现在添加了一个方法来执行 ping 并根据以下内容更改 UI Ping 结果

    private void ExecPingAndChangeUI()
    {
        runtime = 0; //reset runtime
        delayins = interval / 1000; // umwandeln in Sekunden
        if (comboBox1.SelectedItem != null) //Überprüfen ob ein Element in der Combobox ausgewählt wurde
        {
            value = (comboBox1.SelectedItem as dynamic).Value; //Auslesen der Combobox
            status = Ping(value); //Auslesen des Ping ergebnisses

            if (status == true)
            {
                //Ausgabe an OutputLabel
                labelOutput.Text = "Address      : " + Environment.NewLine + value + Environment.NewLine + Environment.NewLine +
                                   "Status       : " + Environment.NewLine + "Success" + Environment.NewLine + Environment.NewLine +
                                   "Laufzeit in s: " + Environment.NewLine + runtime + "s";
                labelOutput.BackColor = System.Drawing.Color.Green;

                if (minIcon.Icon != Properties.Resources.Symbol2)  //ändern Symbol + Test ob symbol schon das ausgewählte ist
                {
                    minIcon.Icon = Properties.Resources.Symbol2;
                }

                if (onetimebubble == false)
                {
                    onetimebubble = true;
                }

                runtime = runtime + delayins; //laufzeit berechnung
            }
            else if (status == false)
            {
                runtime = 0; //Reset Laufzeit     
                //Ausgabe an OutputLabel
                labelOutput.Text = "Address      : " + Environment.NewLine + value + Environment.NewLine + Environment.NewLine +
                                   "Status       : " + Environment.NewLine + "Failed" + Environment.NewLine + Environment.NewLine +
                                   "Laufzeit in s: " + Environment.NewLine + runtime + "s";
                labelOutput.BackColor = System.Drawing.Color.Red;

                if (minIcon.Icon != Properties.Resources.Symbol1) //ändern Symbol + vorheriger test
                {
                    minIcon.Icon = Properties.Resources.Symbol1;
                }

                if (onetimebubble == true) //ausgabe Warnmeldung + vorheriger test 
                {
                    minIcon.ShowBalloonTip(1000);
                    onetimebubble = false;
                }
                runtime = runtime + delayins; //laufzeit berechnung
            }
        }
        else
        {
            labelOutput.Text = "Bitte ein Element auswählen!"; //falls nichts in der Combobox ausgewählt wurde
        }
    }

您可以在方法的开头和结尾添加一行代码 enable/disable

private async void Button1_Click(object sender, EventArgs e) 
{
    Button1.Enabled = false;

    ....
    ....
    ....

    Button1.Enabled = true;
}

这应该可以与 async/await 一起正常工作。

我想推荐 "little" 重构该代码:

封装ping

写一个只有一个目的的 class:发送 ping 和 return 结果。 如果 Ping class 对你来说是一个足够高的抽象,我会将一个实例设为私有 class 属性,它将通过下一段中第 1 点的方法进行配置。

引入计时器

既然您想重复执行 ping,那么为此使用计时器似乎是合理的。这意味着以下步骤:

  1. 有一种方法使用上面提到的 ping class 执行 ping 并根据传递的结果更新 UI。它应该收集执行 ping 所需的所有信息(target、data ...),这样您就可以即时更改 ping 目标,它会在下一个 tick 触发时相应地反映出来。
  2. 更改 button_click 处理程序和包含 class 的内容:

    2.1。有一个 属性 类型的定时器。 (默认 = 空)

    2.2。点击按钮:

    2.2.1。检查计时器 属性 是否不为空: True - 停止计时器和 null 属性(= 停止 ping), 错误 - 继续

    2.2.2。创建一个 Timer ,设置计时器 属性 以引用它并启动它。 timer的tick要执行第1点的方法

备注

您可能希望有第二个按钮来明确停止 ping 而不开始新的 ping。提示:您可以使用 ToggleButton 并使用其状态信息来决定是开始还是停止 ping。

注意:计时器可能会在单独的线程上执行它的滴答处理程序(第 1 点中的方法),具体取决于您使用的计时器实现。因此,您可能需要将 UI-Updates 编组到 UI 线程。有几种可能的方法可以做到这一点。我建议你自己做研究,因为你说你是新手编码员。您将在课程中学到很多

此外,您可能需要确保当计时器触发计时时,最后一次 ping 已 returned(因此它们不会重叠)。

注意:为了改进这个答案,我会添加一些参考资料供您稍后在家使用。

计时器:参见https://msdn.microsoft.com/en-us/library/system.windows.forms.timer(v=vs.110).aspx(里面的代码示例)