计时器冻结我的WPF窗口

时间:2013-08-26 23:17:23

标签: c# wpf timer

我已经阅读了一些关于Timer的主题,并发现System.Timers.Timer已经实现了线程。所以我使用了Dispatcher.Invoke,但我的Timer仍在冻结我的窗口。

我的代码: System.Timers.Timer

        int seconds = 5;
        Timer timerGetSong = new Timer();
        timerGetSong.Elapsed += (o, args) => GetSongTimer();
        timerGetSong.Interval = 1000*seconds;

计时器触发的下一个方法:

        private void GetSongTimer()
        {
            Dispatcher.Invoke(GetLastFmCurrentSong);
        }

最终方法是从Web解析并将值赋给我的TextBlock ...这意味着在分配值之前需要1-2-3秒才能解析:

private void GetLastFmCurrentSong()
{
    CQ dom = CQ.CreateFromUrl("http://www.last.fm/user/nukec");

    string listeningNow = dom["#recentTracks:first .dateCell:first"].Text();

    string track;
    if (listeningNow.Contains("Listening now"))
    {
    track = dom["#recentTracks:first .subjectCell:first"].Text();
    track = track.Replace('\n', ' ');
    }
    else
    {
    track = "Not listening anything";
    }
    TextBlockNameSong.Text = track;
}

那时窗口冻结了。如何正确实现这个?谢谢

1 个答案:

答案 0 :(得分:1)

现在整个GetLastFmCurrentSong()方法被分派到UI线程,这就是它阻塞的原因。您只需要分发尝试访问UI的部分代码。为此,首先为UI线程创建一个全局Dispatcher变量,如下所示:

private Dispatcher currentDispatcher = Dispatcher.CurrentDispatcher;

更改您的GetSongTimer以直接调用GetLastFmCurrentSong()方法(或最终让计时器的Elapsed事件调用它):

private void GetSongTimer()
{
    GetLastFmCurrentSong();
}

最后,将您的GetLastFmCurrentSong()更改为仅使用TextBlockNameSong.Text = track;上的调度程序:

private void GetLastFmCurrentSong()
{
   CQ dom = CQ.CreateFromUrl("http://www.last.fm/user/nukec");

   string listeningNow = dom["#recentTracks:first .dateCell:first"].Text();

   string track;
   if (listeningNow.Contains("Listening now"))
   {
     track = dom["#recentTracks:first .subjectCell:first"].Text();
     track = track.Replace('\n', ' ');
   }
   else
   {
     track = "Not listening anything";
   }

   currentDispatcher.Invoke(new Action(() =>
   {
      TextBlockNameSong.Text = track;
   }));
}