Silverlight Asynchronous Loader Helper

Here’s a potentially useful (or tedium-saving) Silverlight class to simplify asynchronous server requests:

public class AsyncLoader
{
    private Action<Stream> onLoaded;
    private Action<Exception> onError;

    /// <summary>
    /// Loads from the specified URL.
    /// </summary>
    /// <param name="url">The URL.</param>
    /// <param name="onLoaded">The Action to invoke when loaded.</param>
    public static void Load( string url, Action<Stream> onLoaded )
    {
        Load( url, onLoaded, null );
    }

    /// <summary>
    /// Loads from the specified URL.
    /// </summary>
    /// <param name="url">The URL.</param>
    /// <param name="onLoaded">The Action to invoke when loaded.</param>
    /// <param name="onError">The Action to invoke on error.</param>
    public static void Load( string url, Action<Stream> onLoaded, Action<Exception> onError )
    {
        new AsyncLoader( onLoaded, onError ).Load( url );
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="AsyncLoader"/> class.
    /// </summary>
    /// <param name="onLoaded">The on loaded.</param>
    /// <param name="onError">The on error.</param>
    protected AsyncLoader( Action<Stream> onLoaded, Action<Exception> onError )
    {
        this.onLoaded = onLoaded;
        this.onError = onError;
    }

    /// <summary>
    /// Loads from the specified URL.
    /// </summary>
    /// <param name="url">The URL.</param>
    public void Load( string url )
    {
        var wc = new WebClient();
        wc.OpenReadCompleted += OpenReadCompleted;
        wc.OpenReadAsync( new Uri( "../" + url, UriKind.Relative ) );
    }

    /// <summary>
    /// Opens the read completed.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.Net.OpenReadCompletedEventArgs"/> instance containing the event data.</param>
    private void OpenReadCompleted( object sender, OpenReadCompletedEventArgs e )
    {
        if ( e.Error != null )
        {
            if ( onError != null ) onError( e.Error );
        }
        else if ( onLoaded != null )
        {
            try
            {
                onLoaded( e.Result );
            }
            finally
            {
                if ( e.Result != null ) e.Result.Close();
            }
        }
    }
}

It wraps a call to WebClient.OpenReadAsync and simplifies the calling code a little:

private void OnSourceChanged( string source )
{
    AsyncLoader.Load( source, OnLoaded, OnError );
    OnPropertyChanged( "Source" );
}

private void OnLoaded( Stream stream )
{
    var config = XElement.Load( stream );
    var engine = XmlEngineParser.Parse( config );
    var worksheet = engine.CreateWorksheet();

    // Other stuff...
}

private void OnError( Exception ex )
{
    // Handle error
}

As usual, don’t be tempted to update any Silverlight controls in a handler without going through a Dispatcher (to ensure you’re calling on the UI thread), like so:

Dispatcher.BeginInvoke( delegate
{
    // Now you can safely update your UI...
} );

Hope this helps!

One Comment

Leave a comment