【问题标题】:Timer not stopping when form closed表单关闭时计时器不停止
【发布时间】:2013-03-21 20:05:47
【问题描述】:

我遇到了一个非常奇怪的错误,我似乎无法弄清楚。我会尽我所能把这个布置好。

上下文:我有一个应用程序,它会不断地对一组位于不同位置的 IP 进行 ping 操作。 (我们需要查看每个设备是否在给定时间启动)

错误:当 ping 主机时,当他们的互联网关闭时,应用程序显示所有设备都关闭(应该如此)。但是当关闭应用程序时,进程(主应用程序 exe)仍在运行,我们的路由器流量显示持续 ping 仍在运行。(相同的时间间隔)。所以它就像计时器一直在走。

但是当应用程序关闭并且组启动时,进程会正常关闭并且所有 ping 都会停止。

我可以提供你们想看的任何代码。我先介绍一下基础知识:

我有一个名为 EquipmentObj 的类。在构造函数内部,开始连续 ping(异步) *请注意,这都是在单独的表单上完成的,而不是主表单。 构造函数和属性:

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

开始和经过的方法:

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

基类:

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

实现 Ping 完成:

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

最后是我在关闭表单时调用的清理:

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

这里是车站:

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

我尝试过的:

  • 将清理(上图)添加到关闭事件中。
  • 将我的计时器从 system.threading 计时器移至 system.timer 计时器。
  • 我尝试过实现一次性。
  • 在表单关闭事件中将计时器设置为空。
  • 在它自己的计时器上调用 dispose。

这些都没有奏效。 我希望我没有用太多的代码和写作压倒你们所有人。任何帮助,将不胜感激。

【问题讨论】:

  • 我没有看到您实际停止计时器的停止功能。我会停止注销监听器,停止计时器,然后处置并设置为空。如果您想更加安全,请添加检查以查看处理程序中的计时器是否仍然为空
  • 很抱歉。我已经添加了。
  • 为什么在构造函数中调用了start,然后又调用了Start函数?
  • 尝试在停止函数上设置一个断点,看看当连接断开时它是否真的命中它
  • @JeremyK 哇,它没有击中!我刚刚测试过。

标签: c# multithreading asynchronous timer ping


【解决方案1】:

我最好的选择是在调用 Stop 之前抛出异常。我将在其中添加更多 try { } catch 语句,以便您处理错误。

在尝试访问不是在同一线程上创建的对象时,您可能会遇到一些线程问题。

我会检查你是否需要在你弄乱计时器对象时调用。

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

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

【讨论】:

  • 将此标记为答案。不完全是什么问题,但杰里米把我带到了那里。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 1970-01-01
  • 2016-08-15
  • 2014-09-05
相关资源
最近更新 更多