我已经阅读了一些关于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;
}
那时窗口冻结了。如何正确实现这个?谢谢
答案 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;
}));
}