Try an online Silverlight class for free!
Additional Resources

Improving Silverlight Application Performance

In this lesson of the Silverlight tutorial, you will learn...
  1. The difference between synchronous and asynchronous programming techniques
  2. To download large objects asynchronously by using the WebClient

This lesson will introduce Silverlight's ability to asynchronously download large files and data from a server using the WebClient class.

Synchronous vs. Asynchronous Processing

Computers that contain a single processor are only capable of performing a single task at a time. Most laptops that are running Windows, for example, have a single processor (CPU) and are only capable of performing a single task on the computer at a time. If that is the case, how does an elaborate operating system like Windows seemingly perform many concurrent tasks as well as host multiple applications in memory simultaneously with each application also performing tasks? The answer is that the operating system manages the time that the processor allocates to performing each task very efficiently. The operating system allocates an incredibly small slice of the processor's time to each application and task that is in memory. The applications and tasks are then cycled through with each performing a small amount of work. The processor cycles through the applications and tasks very quickly as to give the illusion that multiple tasks are being performed simultaneously.

Each application that is loaded into memory is referred to as a process. Each process typically attempts to perform a single task and so each process is assigned a single thread of execution (a slice of the processor's time) to use to complete the task. Most code is written to perform a single task at a time and to complete the task at hand before continuing on to execute the next task. This type of processing is referred to as synchronous processing. In most scenarios, synchronously executing code is accomplished very quickly and will suffice. Additionally, in most scenarios, most tasks being performed in code are reliant upon the previous task being completed before the task can be performed. For example, when querying a database, the query cannot be executed until a connection to the database is open. Hence the database commands must be performed in a particular order and synchronous processing is a perfect fit.

However, occasionally tasks are performed in code that are not reliant upon other tasks to be completed first. When tasks that can be performed independently can be identified, it would increase performance if the task could be performed in parallel to other tasks being performed by the application. This is possible by intentionally writing code that spawns another thread of execution so that the process (application) is allocated more than one slice of the processor's time. If multiple tasks are performed in parallel by an application, the application is said to be multithreaded (utilizes more than a single thread to perform its work). When tasks are performed in parallel, the call in code from the initial thread that initiates a task to be performed on another thread doesn't have to wait around for the additional task to complete before continuing on. If it did wait for additional threads to complete their work, the tasks would still be performed in series and there would be no benefit to utilizing multiple threads of execution.

When an additional task is performed in parallel on a separate thread, it is referred to as asynchronous processing. Asynchronous processing is more complex than synchronous processing. When a task is performed synchronously, the code that initiated the synchronous task waits on the task to complete before continuing. However, when a task is performed asynchronously, the code that initiated the asynchronous task continues execution immediately and does not wait on the asynchronous task to complete. So what happens when the asynchronous task completes?

When code initiates an asynchronous task, it also directs the asynchronous task to execute a method or function (known as a callback method) once it completes its work.

Asynchronous processing is a perfect fit for time consuming tasks that can be performed independently. Asynchronous processing is being utilized in most of the recent Web technologies. For example, AJAX stands for Asynchronous JavaScript and XML. In AJAX, an asynchronous call is made to the server behind the scenes. The call is independent of the thread that is processing the Web page and interacting with the user, hence UI performance is increased and the user does not have to wait on the call to the server to complete but will see the results when the results are returned.

The WebClient Class

Silverlight includes a class that is used to directly download resources from a Web server, the WebClient class. The WebClient class was formerly called the HTTP Downloader. The WebClient is best suited to directly downloading larger resources from a Web server that may take time to download including images and media files. All networking calls made in Silverlight are asynchronous calls, hence all calls made by the WebClient are asynchronous. The code listing below is used to download an image from the server.

Notice that the code below includes snippets to illustrate downloading a single image as well as downloading a package of images. The WebClient class can be used to download a single file or multiple files. If multiple files are to be downloaded, they should first be packaged and compressed into a zip file. The WebClient class is capable of extracting a single file out of a zip file once the zip file has been downloaded.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ServiceModel;
using System.IO.IsolatedStorage;
using System.IO;
using System.Net;
using System.Windows.Resources;
using System.Windows.Media.Imaging;

namespace AthleteManager
{
 public partial class Page : UserControl
 {
  UserInformation user = new UserInformation();
  string password = "";
  AthleteManager.AthleteInformation.AthleteServiceSoapClient svc;
  WebClient downloader = new WebClient();

  public Page()
  {
   InitializeComponent();

   BasicHttpBinding bind = new BasicHttpBinding();
   EndpointAddress endpoint = new EndpointAddress("http://localhost/AthleteManager/AthleteService.asmx");
   svc = new AthleteManager.AthleteInformation.AthleteServiceSoapClient(bind, 
   endpoint);

   downloader.OpenReadCompleted += new OpenReadCompletedEventHandler(downloader_OpenReadCompleted);
  }

  void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
  {
   // Display an image from a package.
   //StreamResourceInfo photosDownloaded = new StreamResourceInfo(e.Result as 
   Stream, null);
   //string photoToGrab = e.UserState.ToString();
   //StreamResourceInfo photoStream = Application.GetResourceStream(photosDownloaded, 
   new Uri(photoToGrab, UriKind.Relative));
   //BitmapImage bitmap = new BitmapImage();
   //bitmap.SetSource(photoStream.Stream);
   //bitmap.SetSource(e.Result);
   //imgPhoto.Source = bitmap;

   // Display a single image.
   BitmapImage bitmap = new BitmapImage();
   bitmap.SetSource(e.Result);
   imgPhoto.Source = bitmap;
  }

  private void dgAthleteList_SelectionChanged(object sender, EventArgs e)
  {
   AthleteDisplayInfo athlete = (AthleteDisplayInfo)dgAthleteList.SelectedItem;

   // verify that an athlete is selected.
   if (athlete != null)
   {
    txtFirstName.Text = athlete.FirstName;
    txtLastName.Text = athlete.LastName;

    // download a package.
    // downloader.OpenReadAsync(new Uri("Photos/Photos.zip", UriKind.Relative), 
    athlete.AthleteId.ToString() + ".JPG");

    // download a single file.
    downloader.OpenReadAsync(new Uri("Photos/" + athlete.AthleteId.ToString() + 
    ".JPG", UriKind.Relative));
   }
  }
 }
}

In the code above, an instance of the WebClient class is created. A callback method must be supplied prior to making the call. In this code, the OpenReadCompleted event is wired into the OpenReadCompletedEventHandler handler.

Lab: Improving Performance

In this lab, you will use the WebClient class to download content.

Download Images

20 30

In this exercise, you will use the WebClient class to dynamically download and display photos of the athletes.

  1. Modify the Silverlight XAML control. Add an Image control for displaying athlete photos. Ensure that the Image control has a Name assigned to it.
  2. Some photos exist in the sample application, however, you may choose to display photos of your liking. Zip up the images into a single file for the purposes of this exercise. Files may be downloaded individually or as a package.
  3. In the Silverlight control code behind, add code to the Selection Change event of the DataGrid so that the Image control is dynamically updated when the DataGrid selection changes.
  4. Create an instance of the WebClient class as a class member variable.
  5. Assign an event handler to the OpenReadCompleted event of the WebClient class instance in the class constructor.
  6. Make a call to the OpenReadAsync method in the DataGrid SelectionChange event handler. The call to the OpenReadAsync method for the example code is shown below.
    downloader.OpenReadAsync(new Uri("Photos/Photos.zip", UriKind.Relative), athlete.AthleteId.ToString() + ".JPG");
  7. In the callback event handler for the OpenReadCompleted event, display the image returned by the call as shown in the code below:
    void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { StreamResourceInfo photosDownloaded = new StreamResourceInfo(e.Result as Stream, null); string photoToGrab = e.UserState.ToString(); StreamResourceInfo photoStream = Application.GetResourceStream(photosDownloaded, new Uri(photoToGrab, UriKind.Relative)); BitmapImage bitmap = new BitmapImage(); bitmap.SetSource(photoStream.Stream); imgPhoto.Source = bitmap; }
  8. The resulting Silverlight control should resemble the following figure.
Error. This text should not be shown. Please email courseware@webucator.com to report it:

Lab: Improving Performance

In this lab, you will use the WebClient class to download content.

Exercise: Download Images

Duration: 20 to 30 minutes.

In this exercise, you will use the WebClient class to dynamically download and display photos of the athletes.

  1. Modify the Silverlight XAML control. Add an Image control for displaying athlete photos. Ensure that the Image control has a Name assigned to it.
  2. Some photos exist in the sample application, however, you may choose to display photos of your liking. Zip up the images into a single file for the purposes of this exercise. Files may be downloaded individually or as a package.
  3. In the Silverlight control code behind, add code to the Selection Change event of the DataGrid so that the Image control is dynamically updated when the DataGrid selection changes.
  4. Create an instance of the WebClient class as a class member variable.
  5. Assign an event handler to the OpenReadCompleted event of the WebClient class instance in the class constructor.
  6. Make a call to the OpenReadAsync method in the DataGrid SelectionChange event handler. The call to the OpenReadAsync method for the example code is shown below.
    downloader.OpenReadAsync(new Uri("Photos/Photos.zip", UriKind.Relative), athlete.AthleteId.ToString() + ".JPG");
  7. In the callback event handler for the OpenReadCompleted event, display the image returned by the call as shown in the code below:
    void downloader_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
     StreamResourceInfo photosDownloaded = new StreamResourceInfo(e.Result as Stream, null);
     string photoToGrab = e.UserState.ToString();
     
     StreamResourceInfo photoStream = Application.GetResourceStream(photosDownloaded, new Uri(photoToGrab, UriKind.Relative));
     
     BitmapImage bitmap = new BitmapImage();
     
     bitmap.SetSource(photoStream.Stream);
     
     imgPhoto.Source = bitmap;
    }
  8. The resulting Silverlight control should resemble the following figure.

Improving Silverlight Application Performance Conclusion

In this lesson of the Silverlight tutorial, you

  • Reviewed synchronous and asynchronous processing techniques
  • Utilized the WebClient class
To continue to learn Silverlight go to the top of this page and click on the next lesson in this Silverlight Tutorial's Table of Contents.
Last updated on 2009-05-11

Use of http://www.learn-silverlight-tutorial.com (Website) implies agreement to the following:

Copyright Information

All pages and graphics on Website are the property of Webucator, Inc. unless otherwise specified.

None of the content on Website may be redistributed or reproduced in any way, shape, or form without written permission from Webucator, Inc.

No Printing or saving of pages or content on Website

This content may not be printed or saved. It is for online use only.


Linking to Website

You may link to any of the pages on Website; however, you may not include the content in a frame or iframe without written permission from Webucator, Inc.


Warranties

Website is provided without warranty of any kind. There are no guarantees that use of the site will not be subject to interruptions. All direct or indirect risk related to use of the site is borne entirely by the user. All code and explanations provided on this site are provided without warranties to correctness, performance, fitness, merchantability, and/or any other warranty (whether expressed or implied).


For individual private use only

You agree not to use this online manual to deliver or receive training. If you are delivering or attending a class that is making use of this online manual, you are in violation of our terms of service. Please report any abuse to courseware@webucator.com. If you would like to deliver or receive training using this manual, please fill out the form at http://www.webucator.com/Contact.cfm