0
votes

I am having an extremely bizarre bug that I cant seem to figure out. I will lay this out as best as I can.

Context: I have an application that will continually ping about a group of IP's that live in a different location. (We need to see if each device is up at a given time)

Bug: When pinging a host, and their internet is down, the application shows all devices are down (as it should). But when closing the app, the process (main app exe) is still running and our router traffic shows that the continuous ping is still running.(Same interval). So its like the timer keeps going.

But when the application is closed, and the group is up, the process closes as it should and all pings stop.

I can provide any code that you guys want to see. Ill give the basics first:

I have a class called EquipmentObj. Inside the constructor, a contiguous ping gets started (async) *Note this is all done on a seperate form, not the mainform. Constructor and property:

System.Timers.Timer TimerObj { get; set; }
public EquipmentObj(string ipAddress)
        {
                this.IP_Address = ipAddress;
                this.TimerObj = new System.Timers.Timer();
                this.TimerObj.Interval = 2000;
                this.TimerObj.Elapsed += TimerObj_Elapsed;
                this.TimerObj.AutoReset = true;
                this.start();
        }

Start and Elapsed Method:

private void start()
        {
            this._requestStop = false;
            this.TimerObj.Start();
        }


        private void TimerObj_Elapsed(object sender, System.Timers.ElapsedEventArgs     e)
            {
                if(!_requestStop)
                    base.start_Ping(this.Ip_Address);
            }

Base Class:

public void start_Ping(string ipAddress)
        {
            try
            {
                Ping pingSender = new Ping();


                // Create the event Handler 
                pingSender.PingCompleted += pingSender_PingCompleted;

                // Create the buffer
                // Reference buff size: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                byte[] packetData = Encoding.ASCII.GetBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
                // Create the pingOptions object
                PingOptions packetOptions = new PingOptions();
                // Parse the passed ip address to a proper ipaddress object
                IPAddress ip = System.Net.IPAddress.Parse(ipAddress);

                // Send async
                pingSender.SendAsync(ip, 1050, packetData, ip);
            }
            catch (Exception ex)
            {
                Error_Log.write_log(ex);
            }
        }

        public virtual void pingSender_PingCompleted(object sender, PingCompletedEventArgs e)
        {
            throw new NotImplementedException();
        }

Implemented Ping Complete:

  public override void pingSender_PingCompleted(object sender, PingCompletedEventArgs e)
        {
            if (e.Reply.Status == IPStatus.Success)
                this.status = "On Line";
            else
            {
                this.status = "Off Line";
                this.setBounced = ++this.setBounced  ?? 1;
            }
            this.setResponse = e.Reply.RoundtripTime.ToString();
        }

Finally my cleanup which is called on the form closing:

 foreach (EquipmentObj obj in this.objectListView1.Objects)
                {
                    obj.Stop();
                }

Here is the stop:

public void Stop()
       {
           this._requestStop = true; 
           this.TimerObj.Stop();
       }

What I've tried:

  • Adding the cleanup (Above) into the closing event.
  • Moved my timer from a system.threading timer, to system.timer timer.
  • I've tried implementing idisposable.
  • Setting Timers to null on form closing event.
  • Calling dispose on the timer it self.

None of these have worked. I hope I didn't over whelm you all with too much code and writing. Any help would be appreciated.

1
I Don't see your Stop function where you actually stop the timer. I would stop the unregister the listener, stop the timer, then dispose and set to null. If you want to be extra safe, add a check to see if the timer is still null or not in the handler - JeremyK
Sorry about that. I have added it. - Botonomous
Why do you call start in the constructor but then call it again the Start function? - JeremyK
Try putting a breakpoint on the stop function and see if it actually hits it when the connection is down - JeremyK
@JeremyK Wow, its not hitting! I just tested. - Botonomous

1 Answers

0
votes

My best bet is you have an exception being thrown prior to the Stop being called. I will put some more try { } catch statements in there so you can handle errors.

You may have some threading issues where you are trying to access objects not created on the same thread.

I would check if you need to Invoke anytime you mess with the timer object.

void Stop()
{
    if (objectListView1.InvokeRequired)
    {
         objectListView1.BeginInvoke(new Action(Stop));
         return;
    }

    foreach (EquipmentObj obj in this.objectListView1.Objects)
    {
        obj.Stop();
    }
}