2011-11-06 96 views
2

我是Windows Phone 7開發新手,如果願意,可以在「後臺」下載一些數據,但有點麻煩。我知道這是可能的,因爲像ESPN等應用程序顯示「加載......」。同時下載他們的數據,並且UI仍然完全響應。我想要做的是下載一些Twitter數據。非阻止下載

這是我現在有,但它是ATM阻塞:

// 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 
            }; 
     }); 
    } 
} 
+0

您的代碼是不會阻止。 (這就是'異步'的意思) – SLaks

+0

@SLaks:我知道這就是Async的意思,我知道它/不應該/被阻止,但它是。我的應用程序的不同部分是否可能被阻止?也許實際繪製的清單?它被設置爲(我認爲)一個綁定?我一直在做總計約4小時的MS編程,所以我希望我沒有提出真正明顯的問題。 – Josh

+0

它不應該阻止。你的回調函數是不是花了很多時間?如果你有大量的數據要彙集。 – abhinav

回答

1

您有兩種選擇:HttpWebRequestWebClient。這兩個類都在後臺下載。唯一區別:使用WebClient方法twitter_DownloadStringCompleted將在UI線程中調用,因此解析數據將阻止UI。

如果使用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)將在UI線程中調用。將您的進度條設置爲StartTwitterUpdate,並將您的進度條設置爲在(2)中不可見。

看看這個類來簡化HTTP調用(POST,FILES,GZIP等):

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

+0

謝謝,我會檢查出來的! – Josh

5

我認爲WebClient方法是部分阻塞。包括DNS查找的第一部分是阻止,但下載本身不是。

C# async methods still hang 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

+0

這絕對聽起來像我正在處理的,但我不確定如何根據該線程中給出的響應來解決它。 – Josh

+0

@Josh使用一個單獨的線程來啓動下載。 – CodesInChaos

+0

我已更新我的問題,但似乎沒有工作。我可能誤解了如何開始一個線程。 – Josh