首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >非阻塞下载

非阻塞下载
EN

Stack Overflow用户
提问于 2011-11-06 19:10:45
回答 2查看 1.1K关注 0票数 2

我是Windows Phone 7开发的新手,如果你愿意的话,我很难找到如何在“后台”下载一些数据。我知道这是可能的,因为像ESPN这样的应用程序会显示一个“加载.”。同时下载他们的数据,用户界面仍然是完全响应。我想要做的是下载一些推特数据。

这是我现在拥有的,但是它阻塞了atm:

代码语言:javascript
复制
// 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
                               };

}

编辑:尝试多线程:

代码语言:javascript
复制
// 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,这是里科·苏特的建议,在博客文章的帮助下,我想我已经做到了:

代码语言:javascript
复制
// 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
                                     };
      });
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-08 00:00:08

您有两个选项:HttpWebRequestWebClient。两个类都在后台下载。唯一的区别是:使用WebClient,方法twitter_DownloadStringCompleted将在UI线程中被调用,因此数据解析将阻止UI。

如果使用HttpWebRequest,则将在另一个线程中调用该方法,但要设置数据绑定或直接到控件的数据,则必须使用以下内容:

代码语言:javascript
复制
void twitter_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    // do your parsing with e.Result...
    Deployment.Current.Dispatcher.BeginInvoke(() => {
        // set your data (2) to UI
    });
}

(2)中的代码将在UI线程中调用。在StartTwitterUpdate中将进度条设置为可见,在(2)中将进度条设置为不可见。

请查看此类以简化http调用(POST、FILES、GZIP等):

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

票数 1
EN

Stack Overflow用户

发布于 2011-11-06 19:14:50

我认为WebClient方法是部分阻塞的。第一部分,包括DNS查找是阻塞的,但下载本身不是。

请参阅C#异步方法仍然挂起UI

就我个人而言,我认为这是.net API中的一个bug (甚至更糟:被设计破坏了)

作为一种解决办法,您可以在一个单独的线程中启动下载。为此,我建议使用tasks。

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

不是最优的,因为它在执行DNS查找时占用线程,但在实践中应该是可以接受的。

我认为代码的另一个问题是回调不会发生在主线程上,而是在线程池线程上。您需要使用一个将事件发布到主线程的SynchronizationContext

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8029642

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档