1

我有一个应用程序,它会定期对服务器进行 ping 操作,以便为您提供连接延迟。从我读过的System.Timers.Timer内容来看,它是在与 UI 不同的线程上运行的。

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

我有一个NotifyIcon显示ContextMenu这个 ping 的结果。但是我注意到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;
            }
4

2 回答 2

2

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

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

它不会自动生成它自己的线程。如果它确实生成了自己的线程,那么在尝试更新控件而不使用Invokeor时会出现异常BeginInvoke

我会使用一个BackgroundWorker对象来执行此操作,该对象的DoWork处理程序包含一个带有 a 的循环Thread.Sleep。然后在循环中执行所有慢 ping 工作DoWork,并拥有一个 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));
    }
}
于 2013-04-08T13:44:04.107 回答
2

这完全取决于 Send 方法的_pvpnetClient运行时间。

你正在运行一个System.Windows.Timer(我知道是因为这个Tick事件),所以这个方法将在主线程上调用,它会阻止所有的 GUI 更新,直到它完成。如果您想在另一个线程上完成工作,您可以使用该System.Timers.Timer对象,但您必须调用回主线程来更新 GUI 元素。

于 2013-04-08T13:45:16.017 回答