Make WPF Image load async

前端 未结 2 1165
[愿得一人]
[愿得一人] 2020-11-27 17:58

I would like to load Gravatar-Images and set them from code behind to a WPF Image-Control. So the code looks like

imgGravatar.Source = GetGravatarImage(emai         


        
2条回答
  •  北海茫月
    2020-11-27 18:55

    I can't see why your code would block the UI, as BitmapImage supports downloading image data in the background. That's why it has an IsDownloading property and a DownloadCompleted event.

    Anyway, the following code shows a straightforward way to download and create the image entirely in a separate thread (from the ThreadPool). It uses a WebClient instance to download the whole image buffer, before creating a BitmapImage from that buffer. After the BitmapImage is created it calls Freeze to make it accessible from the UI thread. Finally it assigns the Image control's Source property in the UI thread by means of a Dispatcher.BeginInvoke call.

    ThreadPool.QueueUserWorkItem(
        o =>
        {
            var url = GravatarImage.GetURL(
               "http://www.gravatar.com/avatar.php?gravatar_id=" + email);
            var webClient = new WebClient();
            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));
        });
    

    EDIT: today you would just use async methods:

    var url = GravatarImage.GetURL(
        "http://www.gravatar.com/avatar.php?gravatar_id=" + email);
    var httpClient = new HttpClient();
    var responseStream = await httpClient.GetStreamAsync(url);
    var bitmapImage = new BitmapImage();
    
    using (var memoryStream = new MemoryStream())
    {
        await responseStream.CopyToAsync(memoryStream);
    
        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = memoryStream;
        bitmapImage.EndInit();
        bitmapImage.Freeze();
    }
    
    image.Source = bitmapImage;
    

提交回复
热议问题