Monday, January 4, 2010

Asynchronous Image Loading in Silverlight

So one task that was bugging me today was doing image loading asynchronously so as to not drag the app down. Now there are some 'xaml' ways of doing this in wpf and supposedly in SL but alas I have not seem it work well. I'm working on a larger class that does this better but here is the basics of how I got it to work in C# code... to start with lets take a look at the following code:


WebClient client = new WebClient();
client.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);

if (ImagePath.IndexOf("http") < 0)
{
string URL = System.Windows.Browser.HtmlPage.Document.DocumentUri.AbsoluteUri;
ImagePath = URL.Substring(0, URL.LastIndexOf('/')) + "/" + ImagePath;
}

client.OpenReadAsync(new Uri(ImagePath, UriKind.RelativeOrAbsolute), ImagePath);

this code lived in the constructor of the class I made. Basically its a user control that replaces the image tag so I can use it in Xaml or programatically etc. in this case I needed to use it programmatically to generate this image 'effect' that I was working on so I passed it into the constructor. the key to the code above is it creates a web client, then checks the url and finally calls the async method that loads the image.

the next bit of code is the event handler:

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
try
{
BitmapImage ImageToLoad = new BitmapImage();
ImageToLoad.SetSource(e.Result as Stream);
TargetImage.Source = ImageToLoad;
}
catch (Exception)
{ }
}

this code is simple enough. Basically the BitmapImage is created and we load the result as a stream into it and then use that to set the source on an image. At least for me this seemed to work well. I'll probably add a few other features namely some reference counting so when I load 1000 of these it doesn't try to grab them all at once...

2 comments:

  1. Hello:

    I was wondering if you have any ideas about loading the images only when they are visible or loading them one by one. In my example I have to load 1000 images. But if the user want to cancel loading the images they should be able to . Right now the Silvelright is still trying to fetch the images even when the control got reset. Any ideas about improving performance will be appreciated. Paging is not an option at this point.

    ReplyDelete
  2. Here is my version of async loading using attached properties and support for only loading a max number concurrently and supporting cancellation.

    http://filenotfoundexception.wordpress.com/2011/02/18/async-image-loading-in-silverlight/

    ReplyDelete