2010-10-02 20 views
6

में कॉल करता है मैं आज WP7 ऐप्स के साथ प्रयोग कर रहा हूं और एक दीवार को थोड़ा सा मारा है। मुझे यूआई और मुख्य ऐप कोड के बीच पृथक्करण होना पसंद है लेकिन मैंने दीवार को मारा।Async WP7

मैंने सफलतापूर्वक एक वेब क्लाइंट अनुरोध लागू किया है और परिणाम प्राप्त किया है, लेकिन क्योंकि कॉल as ascc है, मुझे नहीं पता कि यह बैकअप यूआई स्तर पर कैसे पास किया जाए। मैं पूर्ण या कुछ भी प्रतिक्रिया के इंतजार में हैक लगाना प्रतीत नहीं कर सकता। मुझे कुछ गलत करना होगा।

(यह मैं अपनी वेबसाइट पर डाउनलोड के लिए है कि xbox360Voice पुस्तकालय है: http://www.jamesstuddart.co.uk/Projects/ASP.Net/Xbox_Feeds/ जो मैं एक परीक्षण के रूप WP7 के लिए पोर्टिंग हूँ):

internal const string BaseUrlFormat = "http://www.360voice.com/api/gamertag-profile.asp?tag={0}"; 
    internal static string ResponseXml { get; set; } 
    internal static WebClient Client = new WebClient(); 

    public static XboxGamer? GetGamer(string gamerTag) 
    { 
     var url = string.Format(BaseUrlFormat, gamerTag); 

     var response = GetResponse(url, null, null); 

     return SerializeResponse(response); 
    } 

    internal static XboxGamer? SerializeResponse(string response) 
    { 
     if (string.IsNullOrEmpty(response)) 
     { 
      return null; 
     } 

     var tempGamer = new XboxGamer(); 
     var gamer = (XboxGamer)SerializationMethods.Deserialize(tempGamer, response); 

     return gamer; 
    } 

    internal static string GetResponse(string url, string userName, string password) 
    { 


      if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password)) 
      { 
       Client.Credentials = new NetworkCredential(userName, password); 
      } 

      try 
      { 
       Client.DownloadStringCompleted += ClientDownloadStringCompleted; 
       Client.DownloadStringAsync(new Uri(url)); 

       return ResponseXml; 
      } 
      catch (Exception ex) 
      { 
       return null; 
      } 
     } 



    internal static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 
    { 
     if (e.Error == null) 
     { 
      ResponseXml = e.Result; 
     } 
    } 

और इस

यहाँ

बैकएंड कोड स्निपेट है

public void GetGamerDetails() 
{ 
    var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r"); 
    var xboxGamer = xboxManager.GetGamer(); 

    if (xboxGamer.HasValue) 
    { 
     var profile = xboxGamer.Value.Profile[0]; 
     imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl)); 
     txtUserName.Text = profile.GamerTag; 
     txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000"); 
     txtZone.Text = profile.PlayerZone; 
    } 
    else 
    { 
     txtUserName.Text = "Failed to load data"; 
    } 
} 

अब मैं समझता हूँ मैं ClientDownloadStringCompleted में कुछ जगह की जरूरत है, लेकिन मैं अनिश्चित क्या हूँ: सामने के छोर कोड है।

उत्तर

6

आपके पास समस्या यह है कि जैसे ही कोड पथ में एक एसिंक्रोनस ऑपरेशन पेश किया जाता है, पूरे कोड पथ को अतुल्यकालिक बनने की आवश्यकता होती है।

  • क्योंकि GetResponse कॉल DownloadStringAsync यह अतुल्यकालिक बन जाना चाहिए, यह एक स्ट्रिंग वापस नहीं लौट सकते, यह केवल ऐसा कर सकते हैं एक कॉलबैक
  • पर क्योंकि GetGamer कॉल GetResponse जो अब यह एक XboxGamer वापस नहीं लौट सकते अतुल्यकालिक, यह केवल कॉलबैक
  • पर कॉल कर सकता है GetGamer जो अब असीमित है, यह कॉल के बाद अपने कोड के साथ जारी नहीं रख सकता है, यह केवल GetGamer से कॉल प्राप्त करने के बाद ही ऐसा कर सकता है।
  • क्योंकि GetGamerDetails अब असीमित कुछ भी कहता है, इसे इस व्यवहार को भी स्वीकार करना चाहिए।
  • .... यह श्रृंखला के शीर्ष तक सभी तरह से जारी है जहां एक उपयोगकर्ता घटना होगी।

यहां कुछ एयर कोड है जो कोड में कुछ एसिंक्रोनिटी को खटखटाते हैं।

public static void GetGamer(string gamerTag, Action<XboxGamer?> completed) 
{ 
    var url = string.Format(BaseUrlFormat, gamerTag); 

    var response = GetResponse(url, null, null, (response) => 
    { 
     completed(SerializeResponse(response)); 
    }); 
} 


internal static string GetResponse(string url, string userName, string password, Action<string> completed)  
{  

    WebClient client = new WebClient(); 
    if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))  
    {  
     client.Credentials = new NetworkCredential(userName, password);  
    }  

    try  
    {  
     client.DownloadStringCompleted += (s, args) => 
     { 
      // Messy error handling needed here, out of scope 
      completed(args.Result); 
     }; 
     client.DownloadStringAsync(new Uri(url));   
    }  
    catch  
    {  
     completed(null);  
    }  
}  


public void GetGamerDetails()    
{    
    var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");    
    xboxManager.GetGamer((xboxGamer) =>    
    { 
     // Need to move to the main UI thread. 
     Dispatcher.BeginInvoke(new Action<XboxGamer?>(DisplayGamerDetails), xboxGamer); 
    }); 

} 

void DisplayGamerDetails(XboxGamer? xboxGamer) 
{ 
    if (xboxGamer.HasValue)    
    {    
     var profile = xboxGamer.Value.Profile[0];    
     imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));    
     txtUserName.Text = profile.GamerTag;    
     txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");    
     txtZone.Text = profile.PlayerZone;    
    }    
    else    
    {    
     txtUserName.Text = "Failed to load data";    
    }   
} 

जैसा कि आप एसिंक प्रोग्रामिंग को वास्तविक गन्दा प्राप्त कर सकते हैं।

+0

"जैसा कि आप एसिंक प्रोग्रामिंग देख सकते हैं वास्तव में गन्दा हो सकता है।" ... जो एफ # का उपयोग करने का एक कारण है। एफ # के साथ आप सभी कॉलबैक-इनवर्जन-ऑफ-कंट्रोल somersaults किए बिना कोड को एसिंक को दोबारा कर सकते हैं। – Brian

+0

@ ब्रायन: मैं पूरी तरह से सहमत हूं। मैं बस काम करता हूं कि कार्यात्मक प्रोग्रामिंग को और अधिक सुलभ बनाया जा सकता है, शायद यह युवा दिमागों के लिए है, लेकिन इससे कोई फर्क नहीं पड़ता कि मैं कितनी मेहनत करता हूं, मुझे अवधारणाओं को मेरे अंदर रखने के लिए नहीं मिल सकता है। – AnthonyWJones

+0

बीमार यह कल जाने के लिए धन्यवाद – JamesStuddart

2

आपके पास आमतौर पर 2 विकल्प होते हैं। या तो आप अपने बैकएंड कोड को एसिंक एपीआई के रूप में भी बेनकाब करते हैं, या आपको GetResponse में कॉल को पूरा करने की प्रतीक्षा करनी होगी।

इसे करने से एसिंक मार्ग का मतलब प्रक्रिया को एक स्थान शुरू करना होगा, फिर वापस आएं, और डेटा उपलब्ध होने पर यूआई अपडेट होगा। यह आम तौर पर पसंदीदा तरीका है, क्योंकि यूआई थ्रेड पर अवरुद्ध करने वाली विधि को कॉल करने से आपके ऐप को तब तक अनुत्तरदायी लगेगा जब तक कि विधि चल रही हो।

+0

क्या आपके पास इसका कोई उदाहरण है, क्योंकि मैं समझता हूं कि 'मैं इसे कैसे कर सकता हूं' लेकिन मुझे नहीं पता कि इसे कैसे कार्यान्वित किया जाए। मैंने किसी भी एसएल को पहले या तो एक सीधी सीखने की वक्र पर किया है। – JamesStuddart

1

मुझे लगता है कि "सिल्वरलाइट वे" databinding का उपयोग करना होगा। आपके XboxGamer ऑब्जेक्ट को INotifyPropertyChanged इंटरफ़ेस को कार्यान्वित करना चाहिए। जब आप GetGamer() को कॉल करते हैं तो यह तुरंत "खाली" XboxGamer ऑब्जेक्ट (शायद GamerTag == "लोड हो रहा है ..." या कुछ के साथ) देता है। आपके क्लाइंटडाउनलोडस्ट्रिंग में पूर्ण हैंडलर में आपको लौटाए गए एक्सएमएल को deserialize करना चाहिए और फिर INotifyPropertyChanged.PropertyChanged ईवेंट को आग लगाना चाहिए।

यदि आप एसडीके में "विंडोज फोन डाटाबेस एप्लिकेशन" प्रोजेक्ट टेम्पलेट देखते हैं, तो ItemViewModel क्लास इस तरह कार्यान्वित किया जाता है।

+0

धन्यवाद, ऐसा लगता है कि मैं क्या देख रहा हूं। मैंने टेम्पलेट को देखा (जैसा कि इसे 'नई परियोजना' विंडो में देखा गया था, लेकिन एक नहीं बनाया) बीमार इसे जाने दो। – JamesStuddart

0

Here यह है कि आप WP7 पर किसी भी प्रकार के एसिंक्रोनस फीचर्स का पर्दाफाश कैसे कर सकते हैं।