我想创建一个简单的新闻源,我使用web API获取新闻更新,用户可以使用combox选择类别(世界新闻和体育新闻),并且新闻将每5秒自动更新一次,如果我只选择一次,新闻源可以自动更新并重复,但如果我更改选择,它会开始向我显示这两个类别。这是我的代码
public async void NewsRepeat()
{
RootObject2 myNews = await NewsProxy.GetNews();
RootObject3 mySportNews = await sportsNewsProxy.GetSportNews();
if (newsTpye.SelectedIndex==0)
{
for ( k = 0; k <= 8; k++)
{
newsImage.Source = new BitmapImage(new Uri(myNews.articles[k].urlToImage, UriKind.Absolute));
showTime.Text = myNews.articles[k].publishedAt.ToString();
showDescription.Text = "(" + myNews.source + "): " + myNews.articles[k].description;
await Task.Delay(5000);
}
}
else if (newsTpye.SelectedIndex==1)
{
for (k = 0; k <= 8; k++)
{
newsImage.Source = new BitmapImage(new Uri(mySportNews.articles[k].urlToImage, UriKind.Absolute));
showTime.Text = mySportNews.articles[k].publishedAt;
showDescription.Text = "(" + mySportNews.source + "): " + mySportNews.articles[k].description;
await Task.Delay(5000);
}
}
NewsRepeat();
}
private void newsType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
NewsRepeat();
}
答案 0 :(得分:2)
您的代码连续运行/无限循环。 NewsRepeat永远不会完成 - 所以当您更改选择时,您现在正在运行两个NewsRepeat实例并排。再次更改它,你正在运行三个,依此类推。
在SelectionChanged上,你想以某种方式阻止上一个NewsRepeat实例运行。
(另外,在ViewModel中创建BitmapImages通常是一个坏主意 - 直接在XAML中绑定到URL属性 - Windows将为您执行一些性能和内存增强)
一种可能的解决方案是使用CancellationTokenSource,这是一个非常简单的对象,您可以使用它在您认为必要时手动抛出OperationCanceledException( 经常用作取消异步任务的模式)。请记住,不自动工作 - 这是你必须要处理的事情。
CancellationTokenSource cts = null;
public async void NewsRepeat()
{
cts?.Cancel();
try
{
var localCts = cts = new CancellationTokenSource();
RootObject2 myNews = await NewsProxy.GetNews();
RootObject3 mySportNews = await sportsNewsProxy.GetSportNews();
localCts.Token.ThrowIfCancellationRequested();
if (newsTpye.SelectedIndex == 0)
{
for (k = 0; k <= 8; k++)
{
newsImage.Source = new BitmapImage(new Uri(myNews.articles[k].urlToImage, UriKind.Absolute));
showTime.Text = myNews.articles[k].publishedAt.ToString();
showDescription.Text = "(" + myNews.source + "): " + myNews.articles[k].description;
await Task.Delay(5000);
localCts.Token.ThrowIfCancellationRequested();
}
}
else if (newsTpye.SelectedIndex == 1)
{
for (k = 0; k <= 8; k++)
{
newsImage.Source = new BitmapImage(new Uri(mySportNews.articles[k].urlToImage, UriKind.Absolute));
showTime.Text = mySportNews.articles[k].publishedAt;
showDescription.Text = "(" + mySportNews.source + "): " + mySportNews.articles[k].description;
await Task.Delay(5000);
localCts.Token.ThrowIfCancellationRequested();
}
}
NewsRepeat();
}
catch (OperationCanceledException)
{
// Swallow this exception only - this is probably
// the one we've thrown ourselves
}
}
private void newsType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
NewsRepeat();
}