2013-04-16 4 views
7

बनाएं मैं ग्रेवटर-छवियों को लोड करना चाहता हूं और उन्हें कोड से पीछे एक WPF छवि-नियंत्रण में सेट करना चाहता हूं। तो कोड लग रहा हैWPF छवि लोड async

imgGravatar.Source = GetGravatarImage(email); 

कहाँ GetGravatarImage तरह लग रहा है जैसे:

BitmapImage bi = new BitmapImage(); 
bi.BeginInit(); 
bi.UriSource = new Uri(GravatarImage.GetURL("http://www.gravatar.com/avatar.php?gravatar_id=" + email) , UriKind.Absolute); 
bi.EndInit(); 
return bi; 

दुर्भाग्य से इस जीयूआई ताले जब नेटवर्क कनेक्शन धीमा है। क्या छवि-स्रोत असाइन करने का कोई तरीका है और इसे यूआई को अवरुद्ध किए बिना पृष्ठभूमि में छवि को लोड करने दें?

धन्यवाद!

उत्तर

0

आप इस सवाल पर एक नज़र लेने के लिए चाहते हो सकता है:

Link

और मैं एक Asynchrone कार्य प्रारंभ करेंगे करने के लिए सिफारिश करेंगे, और कोड है कि उस कार्य में async होने की जरूरत है डाल दिया।

19

मैं आपको XAML से अपने imgGravatar पर बाइंडिंग का उपयोग करने का सुझाव देता हूं। IsAsync = true सेट करें और WPF स्वचालित रूप से आपकी छवि खींचने के लिए थ्रेड पूल से थ्रेड का उपयोग करेगा। आप एक IValueConverter में हल करने के तर्क को संपुटित सकता है और केवल स्रोत

रूप में ईमेल बाँध XAML में

:

<Window.Resouces> 
    <local:ImgConverter x:Key="imgConverter" /> 
</Window.Resource> 

... 


<Image x:Name="imgGravatar" 
     Source="{Binding Path=Email, 
         Converter={StaticResource imgConverter}, 
         IsAsync=true}" /> 
संहिता में

:

public class ImgConverter : IValueConverter 
{ 
    public override object Convert(object value, ...) 
    { 
     if (value != null) 
     { 
      BitmapImage bi = new BitmapImage(); 
      bi.BeginInit(); 
      bi.UriSource = new Uri( 
       GravatarImage.GetURL(
        "http://www.gravatar.com/avatar.php?gravatar_id=" + 
         value.ToString()) , UriKind.Absolute 
       ); 
      bi.EndInit(); 
      return bi;     
     } 
     else 
     { 
      return null; 
     } 

    } 
} 
+1

BitmapImage भी एक [उरी पैरामीटर के साथ निर्माता] है (http://msdn.microsoft.com/en-us/library/ms602473.aspx) है, जो आप BeginInit/EndInit कॉल की बचत होगी। – Clemens

+0

+1 इसके बारे में नहीं पता था, अच्छा संकेत। मैंने अभी लेखक से कोड कॉपी किया है और वास्तविक डाउनलोडिंग को अनुकूलित करने के बारे में नहीं सोचा था, इसके बजाय मैंने यूआई ब्लॉक मुद्दे को एक सुरुचिपूर्ण तरीके से हल करने पर ध्यान केंद्रित किया (और निश्चित रूप से यह ब्लॉक करता है, अगर कोड एसिंक नहीं है)। मुझे दोहराव के उपयोग के बारे में लगता है, कनवर्टर को बाध्यकारी से पूरा यूआरएल ईमेल की बजाय अधिक पुन: प्रयोज्य होने के लिए भी मिल सकता है। मैं 'थ्रेडपूल' का उपयोग करके नापसंद करता हूं क्योंकि आपको हर समय प्रेषण का प्रबंधन करना होता है। यह शुद्ध एमवीवीएम अनुप्रयोग के लिए मेरे लिए पर्याप्त सुरुचिपूर्ण नहीं बनाता है। – JanW

+0

क्या आप स्पष्टीकरण दे सकते हैं कि बिटमैप इमेज क्यों बनाते हैं जब अतुल्यकालिक रूप से नहीं कहा जाता है। फिर इसके पास 'IsDownloading' प्रॉपर्टी और' डाउनलोड पूर्ण 'ईवेंट क्यों है। यदि आप एक्सएएमएल में एक छवि नियंत्रण की 'स्रोत' संपत्ति को एक यूआरएल पर सेट करते हैं जो वेब पर एक बड़ी छवि का संदर्भ देता है, तो यूआई ब्लॉक नहीं करेगा। इसके बजाय WPF पृष्ठभूमि में छवि को डाउनलोड करता है और जैसे ही डाउनलोड समाप्त हो जाता है, इसे दिखाता है। – Clemens

6

मैं नहीं देख सकते हैं जिनकी वजह से आपके कोड को ब्लॉक कर देगा UI, बिटमैप छवि पृष्ठभूमि में छवि डेटा डाउनलोड करने का समर्थन करता है। यही कारण है कि इसमें IsDownloading संपत्ति और DownloadCompleted ईवेंट है।

वैसे भी, निम्न कोड छवि को पूरी तरह से एक अलग थ्रेड में डाउनलोड करने और बनाने के लिए एक सीधा तरीका दिखाता है (ThreadPool से)। यह उस बफर से बिटमैप इमेज बनाने से पहले, संपूर्ण छवि बफर डाउनलोड करने के लिए WebClient इंस्टेंस का उपयोग करता है। बिटमैप इमेज के निर्माण के बाद यह यूआई थ्रेड से इसे सुलभ बनाने के लिए Freeze पर कॉल करता है। अंत में यह Dispatcher.BeginInvoke कॉल के माध्यम से UI थ्रेड में छवि नियंत्रण की Source संपत्ति असाइन करता है।

ThreadPool.QueueUserWorkItem(
    o => 
    { 
     var webClient = new WebClient(); 
     var url = GravatarImage.GetURL("http://www.gravatar.com/avatar.php?gravatar_id=" + email); 
     var buffer = webClient.DownloadData(url); 
     var bitmapImage = new BitmapImage(); 

     using (var stream = new MemoryStream(buffer)) 
     { 
      bitmapImage.BeginInit(); 
      bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 
      bitmapImage.StreamSource = stream; 
      bitmapImage.EndInit(); 
      bitmapImage.Freeze(); 
     } 

     Dispatcher.BeginInvoke((Action)(() => image.Source = bitmapImage)); 
    }); 
संबंधित मुद्दे