2015-08-25 9 views
6

मैं एक विंडोज फोन 8.1 ऐप विकसित कर रहा हूं। मेरे पास थंबनेल के साथ समाचार 'शीर्षक की एक सूची है।छवियों को डाउनलोड करते समय Async/डेडलॉक का इंतजार

public class NewsCategory : ObservableObject 
{ 
    ... 
    public string Title { get; set; } 
    public ObservableCollection<News> Items { get; set; } 
} 

समाचार::

public class News : ObservableObject 
{ 
    ... 
    public string Title { get; set; } 
    public string ImagePath { get; set; } 
} 

सबसे पहले मैं

NewsCategories = new NotifyTaskCompletion<ObservableCollection<NewsCategory>>(_newsService.GetNewsCategoriesAsync()); 

NewsCategory (NotifyTaskCompletion pattern संतोषजनक) JSON में समाचार संग्रह प्राप्त करने के लिए अतुल्यकालिक http अनुरोध बना रही हूँ

अभी तक यह पूरी तरह से काम करता है, लेकिन जैसे ही मुझे ImagePath संपत्ति मिलती है, मैं दी गई छवि को डाउनलोड और प्रदर्शित करना चाहता हूं। मुझे इसे अतुल्यकालिक रूप से करने का समाधान मिला है: WP 8.1 Binding image from a http request - ताकि जब xaml छवि पथ प्राप्त हो जाए, तो यह NotifyTaskCompletion पैटर्न का उपयोग करके कनवर्टर क्लास (BinaryToImageSourceConverter) भी कॉल करता है।

समस्या निम्न विधि में होता है:

private async Task<BitmapImage> GetImage(string path) 
{ 
    HttpClient webCLient = new HttpClient(); 
    var responseStream = await webCLient.GetStreamAsync(path); 
    var memoryStream = new MemoryStream(); 
    await responseStream.CopyToAsync(memoryStream); 
    memoryStream.Position = 0; 
    var bitmap = new BitmapImage(); 
    await bitmap.SetSourceAsync(memoryStream.AsRandomAccessStream()); 
    return bitmap; 
} 

जब पहली await कहा जाता है, डिबगर अगली पंक्ति और विधि कभी नहीं देता है तक पहुँचने कभी नहीं। string path परिवर्तनीय में उचित सामग्री है।

अब तक मैंने ConfigureAwait(false) का उपयोग करने का प्रयास किया है, लेकिन यह मेरे मामले में काम नहीं करता है।

मैं भी इस विषय में पता चला है Deadlock while using async await, कि:

जब आप ConfigureAwait(false) उपयोग कर रहे हैं, तो आप अपने कार्यक्रम बता आप संदर्भ के बारे में मन नहीं है। यह कुछ डेडलॉकिंग समस्याओं को हल कर सकता है, लेकिन आमतौर पर सही समाधान नहीं होता है। सही समाधान सबसे अधिक संभावना है कि अवरुद्ध तरीके से कार्यों के लिए कभी भी इंतजार न करें, और सभी तरह से अतुल्यकालिक हो।

मुझे नहीं पता कि मैं उस सामान को अवरुद्ध तरीके से कहां रख सकता हूं। उस डेडलॉक का कारण क्या हो सकता है?

और यदि यह गलत दृष्टिकोण के बारे में है, तो क्या आप किसी भी पैटर्न को जानते हैं जो आइटमों के संग्रह में थंबनेल डाउनलोड करने के लिए अधिक उपयुक्त होगा?

आपकी मदद के लिए धन्यवाद।


अद्यतन: कैसे GetImage शुरू हो जाती है: यह विषय में की तरह है: WP 8.1 Binding image from a http request

public class WebPathToImage : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, string language) 
    { 
     if (value == null) return null; 
     return new NotifyTaskCompletion<BitmapImage>(GetImage((String)value)); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, string language) 
    { throw new NotImplementedException(); } 

    private async Task<BitmapImage> GetImage(string path) 
    { 
     using (var webCLient = new HttpClient()) 
     { 
      webCLient.DefaultRequestHeaders.Add("User-Agent", "bot"); 
      var responseStream = await webCLient.GetStreamAsync(path).ConfigureAwait(false); 
      var memoryStream = new MemoryStream(); 
      await responseStream.CopyToAsync(memoryStream); 
      memoryStream.Position = 0; 
      var bitmap = new BitmapImage(); 
      await bitmap.SetSourceAsync(memoryStream.AsRandomAccessStream()); 
      return bitmap; 
     } 
    } 
} 

और XAML में:

<Image 
DataContext="{Binding ImagePath, Converter={StaticResource WebPathToImage}}" 
Source="{Binding Result}" 
Stretch="UniformToFill" 
Height="79" Width="79"/> 
+3

'GetImage' कैसे शामिल किया गया है? या आप 'Result' या' .Wait' का उपयोग कर इसे अवरुद्ध कर रहे हैं? –

+0

मैंने कोड दिखाने के लिए अपनी पोस्ट संपादित की है। –

+1

मैं सीधे कुछ भी नहीं देख सकता जो गलत हो सकता है। यदि आप इसका एक छोटा, न्यूनतम पुनरुत्पादन कर सकते हैं, तो इससे मदद मिलेगी। –

उत्तर

0

सबसे पहले, यदि आप विंडोज फोन 8.1 पर हैं तो HttpClient नामस्थान Windows.Web.Http से System.Net.Http से उपयोग करने की अनुशंसा की जाती है। this link पर कुछ कारणों को समझाया गया है।

मेरा जवाब का उपयोग करता है नई Windows.Web.Http.HttpClient तो अपने GetImage विधि इस तरह दिख सकता:

 private async Task<BitmapImage> GetImage(string path) 
     { 
      using (var webCLient = new Windows.Web.Http.HttpClient()) 
      { 
       webCLient.DefaultRequestHeaders.Add("User-Agent", "bot"); 
       var responseStream = await webCLient.GetBufferAsync(new Uri(path)); 
       var memoryStream = new MemoryStream(responseStream.ToArray()); 
       memoryStream.Position = 0; 
       var bitmap = new BitmapImage(); 
       await bitmap.SetSourceAsync(memoryStream.AsRandomAccessStream()); 
       return bitmap; 
      } 
     } 

मैं एक नमूना URL पर इस विधि का परीक्षण किया है और यह एक Image नियंत्रण में सही ढंग से प्रदर्शित।

<Image 
    Source="{Binding ImagePath}" 
    Stretch="UniformToFill" 
    Height="79" 
    Width="79" /> 

इस तरह अपने ImagePath एक संसाधन के लिए एक रास्ता हो सकता है:

दूसरा, क्यों तुम सिर्फ कनवर्टर के बिना BitmapImage डाउनलोड करने Image नियंत्रण संभाल, ताकि आपके XAML इस तरह दिखता है न दें इंटरनेट और स्थानीय संसाधन से।

0

प्रयास करें हो सकता है आप Task.Factory में GetImage कॉल करने के लिए कार्य को किसी अन्य धागे में निष्पादित करने के लिए मजबूर करें।

बिटमैप निर्माण पर भी ध्यान दें, आपको इसके साथ समस्या हो सकती है क्योंकि बिटमैप UI थ्रेड में नहीं बनाया गया है।

संबंधित मुद्दे