Неблокирующая загрузка - PullRequest
       3

Неблокирующая загрузка

2 голосов
/ 06 ноября 2011

Я новичок в разработке для Windows Phone 7, и у меня возникли проблемы с поиском, как загрузить некоторые данные в фоновом режиме, если хотите.Я знаю, что это возможно, потому что такие приложения, как ESPN и т. Д., Отображают «Загрузка ... ...».во время загрузки своих данных, и пользовательский интерфейс все еще полностью отзывчив.То, что я пытаюсь сделать, это загрузить некоторые данные из Twitter.

Вот то, что у меня есть сейчас, но он блокирует банкомат:

// Constructor:

// load the twitter data
WebClient twitter = new WebClient();

twitter.DownloadStringCompleted += new DownloadStringCompletedEventHandler(twitter_DownloadStringCompleted);
twitter.DownloadStringAsync(new Uri("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=badreligion"));

// Callback function:

void twitter_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
  if (e.Error != null)
  {
    return;
  }

  XElement xmlTweets = XElement.Parse(e.Result);

  TwitterListBox.ItemsSource = from tweet in xmlTweets.Descendants("status")
                               select new TwitterItem
                               {
                                 ImageSource = tweet.Element("user").Element("profile_image_url").Value,
                                 Message = tweet.Element("text").Value,
                                 UserName = tweet.Element("user").Element("screen_name").Value
                               };

}

РЕДАКТИРОВАТЬ: Попыткапри многопоточности:

// in constructor
Dispatcher.BeginInvoke(new ThreadStart(StartTwitterUpdate));

// other functions
private void StartTwitterUpdate()
{
  // load the twitter data
  WebClient twitter = new WebClient();

  twitter.DownloadStringCompleted += new DownloadStringCompletedEventHandler(twitter_DownloadStringCompleted);
  twitter.DownloadStringAsync(new Uri("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=badreligion"));
}

void twitter_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
  if (e.Error != null)
  {
    return;
  }

  XElement xmlTweets = XElement.Parse(e.Result);

  TwitterListBox.ItemsSource = from tweet in xmlTweets.Descendants("status")
                               select new TwitterItem
                               {
                                 ImageSource = tweet.Element("user").Element("profile_image_url").Value,
                                 Message = tweet.Element("text").Value,
                                 UserName = tweet.Element("user").Element("screen_name").Value
                               };

}

РЕДАКТИРОВАНИЕ 2: Использование HttpWebRequest, как предложено Rico Suter , и с помощью this сообщение в блоге, я думаю, что я сделал это:

// constructor
StartTwitterUpdate();


private void StartTwitterUpdate()
{
  HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=badreligion"));

  request.BeginGetResponse(new AsyncCallback(twitter_DownloadStringCompleted), request);
}

void twitter_DownloadStringCompleted(IAsyncResult asynchronousResult)
{
  HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;

  HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);

  using (StreamReader streamReader1 = 
    new StreamReader(response.GetResponseStream()))
    {
      string resultString = streamReader1.ReadToEnd();

      XElement xmlTweets = XElement.Parse(resultString);

      Deployment.Current.Dispatcher.BeginInvoke(() =>
      {
        TwitterListBox.ItemsSource = from tweet in xmlTweets.Descendants("status")
                                     select new TwitterItem
                                     {
                                       ImageSource = tweet.Element("user").Element("profile_image_url").Value,
                                       Message = tweet.Element("text").Value,
                                       UserName = "@" + tweet.Element("user").Element("screen_name").Value
                                     };
      });
    }
}

Ответы [ 2 ]

5 голосов
/ 06 ноября 2011

Я думаю, что WebClient методы частично блокируются. Первая часть, включающая в себя поиск DNS, - это блокировка, а сама загрузка - нет.

См. Асинхронные методы C # по-прежнему зависают UI

Лично я бы назвал это ошибкой в ​​.net API (или, что еще хуже: сломано по замыслу)

В качестве обходного пути вы можете начать загрузку в отдельном потоке. Для этого я рекомендую использовать API задач.

Task.Factory.StartNew(
  ()=>
  {
      twitter.DownloadStringAsync(new Uri("http://api.twitter.com/1/statuses/user_timeline.xml?screen_name=badreligion"));
  }
);

Не оптимально, так как он занимает поток при выполнении поиска DNS, но должен быть приемлемым на практике.


Я думаю, что другая проблема с вашим кодом заключается в том, что обратный вызов не будет происходить в основном потоке, а в потоке потоков. Вам нужно использовать SynchronizationContext, который отправляет событие в основной поток.

1 голос
/ 08 ноября 2011

У вас есть два варианта: HttpWebRequest и WebClient. Оба класса загружаются в фоновом режиме. Единственное отличие: при WebClient метод twitter_DownloadStringCompleted будет вызываться в потоке пользовательского интерфейса, поэтому анализ данных будет блокировать пользовательский интерфейс.

Если вы используете HttpWebRequest , метод будет вызываться в другом потоке, но для установки данных для привязки данных или непосредственно к элементу управления вы должны использовать что-то вроде этого:

void twitter_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    // do your parsing with e.Result...
    Deployment.Current.Dispatcher.BeginInvoke(() => {
        // set your data (2) to UI
    });
}

Код в (2) будет вызываться в потоке пользовательского интерфейса. Установите индикатор выполнения на StartTwitterUpdate, а индикатор выполнения - на (2).

Проверьте эти классы, чтобы упростить вызовы http (POST, FILES, GZIP и т. Д.):

http://mytoolkit.codeplex.com/wikipage?title=Http

...