1

サーバーに定期的に ping を送信して接続のレイテンシーを提供するアプリケーションがあります。私が読んだことSystem.Timers.Timerから、UI とは別のスレッドで実行されます。

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

この ping の結果を表示する がありますNotifyIcon。しかし、タイマーが刻むたび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;
            }
4

2 に答える 2

2

すべては、Send メソッドの_pvpnetClient実行にかかる時間によって異なります。

あなたはSystem.Windows.Timer(イベントのために知っている)を実行しているTickので、このメソッドはメインスレッドで呼び出され、完了するまですべての GUI 更新をブロックします。別のスレッドで作業を行いたい場合は、System.Timers.Timerオブジェクトを使用できますが、メイン スレッドを呼び出して GUI 要素を更新する必要があります。

于 2013-04-08T13:45:16.017 に答える
2

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

「サーバーベースのタイマーは、マルチスレッド環境のワーカー スレッドで使用するように設計されています。」

独自のスレッドを自動的に生成しません。Invoke独自のスレッドを生成した場合、またはを使用せずにコントロールを更新しようとすると、例外が発生しますBeginInvoke

ハンドラーに a を含むループが含まれているBackgroundWorkerオブジェクトでこれを行います。次に、すべての遅い ping 作業をループ内で実行し、アイコンの更新を取得して実行する 1 つの GUI 関数を用意します。この GUI 関数を Invoke で呼び出して、GUI アクションを GUI スレッドに戻します。DoWorkThread.SleepDoWorkreturnedPing

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 に答える