在无限循环中使用 ping [英] using ping in infinite loop

查看:172
本文介绍了在无限循环中使用 ping的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想持续检查仪器连接.这些仪器通过 LAN 连接.

I want to check the instrument connectivity, continuously. These instruments are connected by LAN.

我无限循环地ping它们.几秒钟后,我遇到了蓝屏并且系统重新启动.

I ping them in an infinite loop. After a few seconds, I'm met with a blue screen and the system restarts.

private async void checkingDevice()
{
    await Task.Run(() =>
    {
        do
        {
            Panel selectedPanel;
            multicastPing.send();
            foreach (var device in (Device[])Enum.GetValues(typeof(Device)))
            {
                selectedPanel = (Panel)this.Controls.Find((device).ToString(), true)[0];
                if (multicastPing.check(device.ToString()))
                    selectedPanel.BackgroundImage = Image.FromFile(Configs.imagesUrl + "enable\\" + selectedPanel.AccessibleName + ".png");
                else
                    selectedPanel.BackgroundImage = Image.FromFile(Configs.imagesUrl + "disable\\" + selectedPanel.AccessibleName + ".png");
            }
        } while (!flag);
        // TODO
        // delete instrument object after using in this snippet code
    });
} 

public bool send()
{
    foreach (var device in (Device[])Enum.GetValues(typeof(Device)))
        replyDictionary[device.ToString()] = sendDictionary[device.ToString()].Send(Configs.instrumentSpecification[device.ToString()].ip).Status;
    return true;
}

推荐答案

我的职业是测试和测量,做这种事情似乎很熟悉.因此,我提供此作为一种方法,看看我是否可以帮助您 ping 您的仪器堆栈.

My career was in Test and Measurement and doing this kind of thing seems quite familiar. So I'm offering this as one approach to see if I can assist you in pinging your instrument stack.

出现蓝屏的情况非常罕见,仅从个人经验来看,很可能是一个非常低级的 IO 内核驱动程序(以太网端口?)遇到了一些糟糕的事情.潜在地,循环似乎可以非常运行到溢出缓冲区的程度?或者,病态地,您可能无意中将 UI 线程绑定到内核驱动程序的线程.哎哟.

Getting a blue screen is pretty rare and just from personal experience it's likely that a very low-level IO kernel driver (ethernet port?) is having a bad time of something. Potentially, it appears that the loop could run very fast to the point of overrunning a buffer perhaps? Or, pathologically, you may inadvertently be binding the UI thread to that of a kernel driver one. Ouch.

我同意有关使用 MethodInvoker 从任务安全调用 UI 线程的评论.但我认为主要问题可能来自这样一个事实,即这个循环尽可能快地运行",这可能非常快.我模拟了类似这样的东西来限制 ping,这样它们每秒发生的次数有限,而且看起来工作正常.

I agree with comments about safely calling the UI thread from a task using MethodInvoker. But I think perhaps the main issue might be coming from the fact that this loop "runs as fast as it can" which might be pretty fast. I modeled something like this that throttles the pings so that they occur some limited number of times per second and it seems to work fine.

一个安全线程的任务,在不阻塞 UI 线程的情况下执行外观看起来像这样:

A safely-threaded task that performs the look without ever blocking on the UI thread looks something like this:

CancellationTokenSource _cts = null;
SemaphoreSlim ssBusy = new SemaphoreSlim(1);
private void ExecMulticastPing()
{
    ssBusy.Wait();
    Task.Run(() =>
    {
        try
        {
            _cts = new CancellationTokenSource();

            do
            {
                List<Task<PingReply>> asyncPings = new List<Task<PingReply>>();

                // Sends out the pings in rapid succession to execute asynchronously in parallel
                foreach (var device in (Device[])Enum.GetValues(typeof(Device)))
                {
                    asyncPings.Add(Task.Run(() => SinglePingAsync(device, _cts.Token)));
                }

                // Waits for all the async pings to complete.
                Task.WaitAll(asyncPings.ToArray());

                // See if flag is already cancelled
                if (_cts.IsCancellationRequested) break;

                foreach (var device in (Device[])Enum.GetValues(typeof(Device)))
                {
                    SetPanelImage(device, asyncPings[(int)device].Result);
                }

                // I believe that it's very important to throttle this to
                // a reasonable number of repeats per second.
                Task.Delay(1000).Wait();
                BeginInvoke((MethodInvoker)delegate
                {
                    WriteLine(); // Newline
                });

            } while (!_cts.IsCancellationRequested); // Check if it's cancelled now
        }
        finally
        {
            ssBusy.Release();
        }
        BeginInvoke((MethodInvoker)delegate
        {
            WriteLine("CANCELLED");
        });
    });
}

...哪里...

const string URL_FOR_TEST = @"www.ivsoftware.com";

private PingReply SinglePingAsync(Device device, CancellationToken token)
{
    if(token.IsCancellationRequested)
    {
        return null;
    }
    Ping pingSender = new Ping();
    PingOptions options = new PingOptions()
    {
        DontFragment = true
    };
    PingReply reply = pingSender.Send(URL_FOR_TEST);
    BeginInvoke((MethodInvoker)delegate
    {
        if (reply.Status == IPStatus.Success)
        {
            WriteLine("Address: " + reply.Address.ToString());
            WriteLine("RoundTrip time: " + reply.RoundtripTime);
            WriteLine("Time to live: " + reply.Options.Ttl);
            WriteLine("Don't fragment: " + reply.Options.DontFragment);
            WriteLine("Buffer size: " + reply.Buffer.Length);
            WriteLine();
        }
        else
        {
            WriteLine("REQUEST TIMEOUT");
        }
    });
    return reply;
}

...和...

private void SetPanelImage(Device device, PingReply reply)
{
    BeginInvoke((MethodInvoker)delegate
    {
        WriteLine("Setting panel image for " + device.ToString() + " " + reply.Status.ToString() );
        Panel selectedPanel = (
            from Control unk in Controls
            where
                (unk is Panel) &&
                (unk.Name == device.ToString()) // ... or however you go about finding the panel...
            select unk as Panel
        ).FirstOrDefault();

        if (selectedPanel != null)
        {
            switch (reply.Status)
            {
                case IPStatus.Success:
                    // Set image for enabled
                    break;
                case IPStatus.TimedOut:
                    // Set image as disabled
                    break;
                default:
                    // Set image as disabled
                    break;
            }
        }
    });
}

这个 10 秒屏幕截图演示这种方法的成功,您可以在我们的 GitHub 存储库中浏览完整的示例代码,如果你认为这会有所帮助.我还在此处回答了一个不同但相关的问题.

This 10-second screen capture demonstrates the success of this approach and you can browse the complete example code on our GitHub repo if you think this would be helpful. I also answered a different-but-related question here.

这篇关于在无限循环中使用 ping的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆