如何在UWP

时间:2017-07-05 01:40:09

标签: asynchronous uwp synchronization

我想创建一个简单的新闻源,我使用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();

    }

1 个答案:

答案 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();
    }