using ping in infinite loop

白昼怎懂夜的黑 提交于 2020-07-08 03:29:09

问题


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

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

回答1:


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.

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.

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.

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

... where ...

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

... and ...

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

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.



来源:https://stackoverflow.com/questions/62259706/using-ping-in-infinite-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!