简体   繁体   中英

Why is setting a XAML Image Source to URI faster than using HttpClient to get the Image?

I'm building a Windows Store App and learning XAML at the same time. I have remote images at a http URI that I want to show in a GridView.

My original solution involved using HttpClient to download the image byte array from the URI, get a RandomAccessStreamReference , construct a BitmapImage , and then set the XAML Image control's source property to the constructed BitmapImage . However, this solution proved to be rather slow (1-2 full seconds to get a single image).

My next solution was to bind the raw URI directly to the XAML Image control's source property directly, which the XAML engine seems to take upon itself to resolve. What used to take 10 seconds to load about 8-10 images suddenly was instant.

Does anyone know how exactly the default URI converter for the XAML Image control resolves the remote image data? It's entirely possible that my first solution was just poorly implemented, but the discrepancy is large enough to pique my curiosity.

Assuming I've found the right piece of code from the ImageSourceConverter class, when you specify the source as a string, the converter is attempting to do this:

    if (((value is string) && !string.IsNullOrEmpty((string) value)) || (value is Uri))
    {
        UriHolder uriFromUriContext = TypeConverterHelper.GetUriFromUriContext(context, value);
        return BitmapFrame.CreateFromUriOrStream(uriFromUriContext.BaseUri, uriFromUriContext.OriginalUri, null, BitmapCreateOptions.None, BitmapCacheOption.Default, null);
    }

BitmapFrame in turn uses a BitmapDecoder to load the image. When the source is a Uri , the BitmapDecoder , amid a bunch of security and sanity checks, uses a WpfWebRequestHelper (undocumented) to request or "download" the image. If the resulting response stream is a valid file, it directly loads the stream into a new FileStream .

Following that, native Windows image decoding functionality takes over to get you your image. Also note that the BitmapDecoder gets cached, so if you're loading multiple images in a row, you don't have the overhead of re-initializing a new BitmapDecoder . Whether that had anything to do with your performance issue I can't say.

In conclusion, I'm guessing that the method WPF uses internally to load images is a highly optimized approach at doing so. I have not looked at the implementation of the HttpClient vs. the likely use of a simple HttpWebRequest to download the image, but I suspect that the overhead of your method was more than that of the built-in method and is what contributed to your slower performance.

If you're wondering how I was able to decipher this information, I simply inspected a few classes within the System.Windows.Media namespace in the PresentationCore assembly using a tool called Reflector .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM