c# - 应用程序滞后于每个计时器滴答

标签 c# winforms timer

我有一个应用程序会定期对服务器执行 ping 操作,以告知您连接的延迟时间。根据我的阅读,System.Timers.Timer 在与 UI 不同的线程上运行。

public MainForm()
{
    InitializeComponent();
    _timer = new Timer();
    _timer.Tick += new EventHandler(timer_Tick);
    _timer.Interval = 1000;
    _timer.Start();
}

我有一个 NotifyIcon 和一个显示此 ping 结果的 ContextMenu。但是我注意到每次计时器滴答时 ContextMenu 都会滞后,我不知道为什么。

编辑:完全忘记添加 timer_tick 函数

            var selectedServer = Properties.Settings.Default.SelectedServer;
            PingReply reply;
            switch (selectedServer)
            {
                case "NA":
                    reply = _pvpnetClient.Send("64.7.194.1");
                    break;
                case "EUW":
                    reply = _pvpnetClient.Send("95.172.65.1");
                    break;
                case "EUN":
                    reply = _pvpnetClient.Send("66.150.148.1");
                    break;
                default:
                    reply = _pvpnetClient.Send("64.7.194.1");
                    break;
            }

            if (reply == null || reply.Status != IPStatus.Success) return;
            var returnedPing = reply.RoundtripTime;

            LoLPing.Text = @"Server: " + selectedServer + @" - Ping: " + reply.RoundtripTime + @"ms";
            PingText.Text = @"Ping: " + reply.RoundtripTime + @"ms";
            if (returnedPing < 120f)
            {
                LoLPing.Icon = Properties.Resources.GreenIcon;
            }
            else if (returnedPing > 120f && returnedPing < 200)
            {
                LoLPing.Icon = Properties.Resources.YellowIcon;
            }
            else
            {
                LoLPing.Icon = Properties.Resources.RedIcon;
            }

最佳答案

http://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.100).aspx

“基于服务器的 Timer 设计用于多线程环境中的工作线程。”

它不会自动生成它自己的线程。如果它确实生成了它自己的线程,那么当您尝试在不使用 InvokeBeginInvoke 的情况下更新您的控件时,您会遇到异常。

我会使用 BackgroundWorker 对象来执行此操作,该对象的 DoWork 处理程序包含一个带有 Thread.Sleep 的循环。然后在 DoWork 循环中执行所有缓慢的 ping 工作,并有一个 GUI 函数接受 returnedPing 并进行图标更新。使用 Invoke 调用此 GUI 函数以将 GUI 操作返回到 GUI 线程。

class SlowOperation
{
    BackgroundWorker m_worker;
    void StartPolling()
    {
        m_worker = new BackgroundWorker();
        m_worker.WorkerSupportsCancellation = true;
        m_worker.WorkerReportsProgress = true;
        m_worker.DoWork += m_worker_DoWork;
        m_worker.ProgressChanged += m_worker_ProgressChanged;
    }

    void m_worker_DoWork(object sender, DoWorkEventArgs e)
    {
        while (!m_worker.CancellationPending)
        {
            int returnedPing = 0;
            // Get my data
            m_worker.ReportProgress(0, returnedPing);
            Thread.Sleep(1000);
        }
    }

    void m_worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        myForm.Invoke(myForm.UpdateMyPing((int)e.UserState));
    }
}

关于c# - 应用程序滞后于每个计时器滴答,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15879013/

相关文章:

C# 字典相当于 Python 的 get() 方法

c# - GhostDoc VisualStudio 扩展加载异常

c# - ValidationMessage 和 ValidationMessageFor 之间的区别

c# - 使用 C# 创建可调整大小的网格以覆盖在图像上

c# - 在 MDI 容器中将每个子窗体作为单独的线程运行

delphi - 只显示一次消息

c# - NPOI Mapper可以设置行号吗

c# - 在 winform 应用程序中使用表单名称打开表单

javascript - 秒倒计时的 jQuery.countdown 问题

iphone - 这段代码中dispatch_after方法是并发执行的吗?