WP7 Problem z wydajnością ściągania RSS

0

Piszę aplikację na panoramie. W jednej z jej itemów pobieram feedy RSS i potem binduje je pod listboxa.

Problem polega na tym, że dopóki wszystko mi się nie ściągnie, to aplikacja wydaje się nie reagować na użytkownika. Tzn, widzę kropeczki ładowania, przesuwam palcem po ekranie kilka razy i w momencie gdy skończy się całe ściąganie itp, przeskakuje tam gdzie być powinienem

Co ciekawe, wystarczy z tego wszystkiego usunąć tylko ustawianie ItemSource - i śmiga jak rakieta:

 namespace SmartStart
{
    public partial class NewsRSS
    {
        MainPage mainPageRef;
        IEnumerable<SyndicationItem> feedSource;

        public NewsRSS(MainPage refDoMainPage)
        {
            this.mainPageRef = refDoMainPage;
            feedLoader();
        }

        public void feedLoader()
        {
            WebClient webClient = new WebClient();
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
            webClient.DownloadStringAsync(new System.Uri("http://rss.cnn.com/rss/edition_world.rss"));

        }

        // Co robimy jak już w końcu się ściągnie?
        private void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            {
               Deployment.Current.Dispatcher.BeginInvoke(() =>
               {
                MessageBox.Show("RSS News feed:\n" + e.Error.Message);
                });
            }
            else
            {
                UpdateFeedList(e.Result);

            }
        }

        private void UpdateFeedList(string feedXML)
        {

            StringReader stringReader = new StringReader(feedXML);
            XmlReader xmlReader = XmlReader.Create(stringReader);
            SyndicationFeed feed = SyndicationFeed.Load(xmlReader);


            feedSource = feed.Items;

            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {               
                mainPageRef.bindNewsListBox(feedSource);
            });
        }

    }

}

Dla formalności, metoda w MainPage

        public void bindNewsListBox(IEnumerable<SyndicationItem> feedSource)
        {
            feedListBox.ItemsSource = feedSource;

        }

Wierzę, że coś pokopałem z wątkami... z tą różnicą, że nie wiem do końca jak to naprawić.
Aczkolwiek, może to zupełnie co innego.

0

Strasznie nie chcę tworzyć takiego bezsensownego posta, ale zależy mi na rozwiązaniu tego problemu, bo nie chcę dodawać kolejnych funkcjonalności na źle działającym kodzie.

Czy ktoś ma z was przynajmniej luźne pomysły co może być nie tak? Cokolwiek, co wam przychodzi do głowy, przynajmniej luźno związane z tematem.

0

Przypuszczam, że problem może leżeć jak opisany tutaj: http://www.visiblox.com/blog/2011/05/common-windows-phone-7-performance-challenges (networking causing UI lags).

0

Też tak myślałem, że to wina webclienta. Bo z tego co się orientowałem, jest to wina tego iż taki ciężki proces jest uruchamiany z wątku na którym został wywołany, czyli najczęściej z UI. Problem polega na tym, że z chwilą wywalenia bindowania (np. z metody tworzącej ItemSource) - śmiga jak rakieta!

Jednak tak czy owak, postanowiłem to przerobić... możliwe, że kompletnie pokopałem te wątki i że się nie znam :P (nawet na to liczę, może ktoś by mi wytłumaczył :) )

NewsRSS:

(w momencie feedSource.Add(Item); zasugerowałem się jakimś gotowym opracowaniem, gdzie w założeniu miał być tworzony osobny wątek do dodawania każdego itema do listy. Problem polega na tym, że mało tego, że nie naprawia to wydajności UI, to artykuły są kompletnie bez sensu: po ~8 kopii tego samego i potem znowu, kilka kopii kolejnego artykułu.)

using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using System.ServiceModel.Syndication;
using System.Xml;
using System.Collections.ObjectModel;
using System;
using System.Threading;


namespace News
{
    public class NewsRSS
    {
        MainPage mainPageRef;
        ObservableCollection<SyndicationItem> feedSource;
  
        public NewsRSS(MainPage refDoMainPage)
        {
            feedSource = new ObservableCollection<SyndicationItem>();
            this.mainPageRef = refDoMainPage;

            mainPageRef.feedListBox.Dispatcher.BeginInvoke(delegate()
            {
                mainPageRef.bindNewsListBox(feedSource);
            });

            feedLoader(); 
        }

        public void feedLoader()
        {
            WebClient webClient = new WebClient();
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
            webClient.DownloadStringAsync(new System.Uri("http://rss.cnn.com/rss/edition_world.rss"));
        }

        // Co robimy jak już w końcu się ściągnie?
        private void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show("Rss napotkał problem");
                });
            }
            else
            {
                // Save the feed into the State property in case the application is tombstoned. 
                mainPageRef.State["feed"] = e.Result;
                mainPageRef.feedListBox.Dispatcher.BeginInvoke(()=>
                {
                UpdateFeedList(e.Result);
                });

            }
        }



        private void UpdateFeedList(string feedXML)
        {
            // Load the feed into a SyndicationFeed instance.
            StringReader stringReader = new StringReader(feedXML);
            XmlReader xmlReader = XmlReader.Create(stringReader);
            SyndicationFeed feed = SyndicationFeed.Load(xmlReader);

            /*Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                mainPageRef.feedListBox.ItemsSource = feed.Items;
            });*/
            
            int itemcounter = 0;
            int sleepcounter = 2;

            foreach (SyndicationItem item in feed.Items)
            {
                itemcounter++;
                if (itemcounter % sleepcounter == 0)
                {
                    System.Threading.Thread.Sleep(20);
                }
                //if (item.PublishDate == DateTime.Today)
                //Deployment.Current.Dispatcher.BeginInvoke(() => {
                

                            feedSource.Add(item);

            }
            
        } 

Konstruktor MainPage.xaml.cs

        public MainPage()
        {
            InitializeComponent();

            Thread th = new Thread(launchNewsClass);
            th.Start();
        }

No i metoda bindująca rzeczy do listboxa.

        private void launchNewsClass()
        {
            nsr = new NewsRSS(this);
        } 

1 użytkowników online, w tym zalogowanych: 0, gości: 1