Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 计时器冻结我的WPF窗口_C#_Wpf_Timer - Fatal编程技术网

C# 计时器冻结我的WPF窗口

C# 计时器冻结我的WPF窗口,c#,wpf,timer,C#,Wpf,Timer,我阅读了一些关于定时器的主题,发现System.Timers.Timer已经实现了线程化。所以我使用了Dispatcher.Invoke,但我的计时器仍然冻结了我的窗口 我的代码: 系统计时器 int seconds = 5; Timer timerGetSong = new Timer(); timerGetSong.Elapsed += (o, args) => GetSongTimer(); timerGetSong.I

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

我的代码: 系统计时器

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

所以那个时候窗户冻结了。如何正确实施??谢谢

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

private Dispatcher currentDispatcher = Dispatcher.CurrentDispatcher;
更改
GetSongTimer
以直接调用
GetLastFmCurrentSong()
方法(或最终让计时器的
已用事件调用它):

最后,将
GetLastFmCurrentSong()
更改为仅在
TextBlockNameSong.Text=track上使用dispatcher

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

从我所读到的内容来看,Dispatcher.Invoke并不是真正用于长时间运行的进程。理想情况下,您应该使用后台工作程序并使用ReportProgress方法来更新ui。您的整个
GetLastFmCurrentSong
被调度到ui线程,这就是它被阻止的原因。您只需要分派正在访问UI的部分代码,即
TextBlockNameSong.Text=track
在您的
GetLastFmCurrentSong
方法中。PoweredByOrange我怎么做?第一次这样做,所以不知道用法。这样使用:你能写下这个作为答案,这样我就可以标记它。感谢you@JohnMathilda就这么做了。您不需要创建本地调度器,尽管这通常是一个好主意,尤其是在需要区分不同的调度器时。谢谢。很好的解释!
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;
   }));
}