Working with Asynchronous Downloading

Dheeraj Kumar Gunti

Reading Time : ( words)


Here is the Sample application which downloads image asynchronously and shows download progress.

Create an iOS Empty Solution and Add a view controller.

Add an UIButton and UIImage to the View Controller in Interface Builder and Create outlets as shown in the below image.



Below is the sample code,

using System;
using Foundation;
using UIKit;
using System.Net;
using CoreGraphics;
using System.IO;
using System.Threading.Tasks;
WebClient webClient;
UIProgressView progressView;
public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    progressView = new UIProgressView (new CGRect (0, this.NavigationController.NavigationBar.Frame.Size.Height,
    UIScreen.MainScreen.Bounds.Width, 10));
    progressView.Progress = 0.0f;
    this.downloadBtn.TouchUpInside += downloadAsync;
}
async void downloadAsync (object sender, System.EventArgs ea)
{
    //Adding Progress View To NavigationBar 
    this.NavigationController.NavigationBar.AddSubview (progressView);
    //Creating Object for WebClient
    webClient = new WebClient ();
    //Taking a large image
    var url = new Uri ("http://photojournal.jpl.nasa.gov/jpeg/PIA15416.jpg");
    byte[] bytes = null;
    webClient.DownloadProgressChanged += HandleDownloadProgressChanged;
    this.downloadBtn.SetTitle ("Cancel", UIControlState.Normal);
    this.downloadBtn.TouchUpInside -= downloadAsync;
    this.downloadBtn.TouchUpInside += cancelDownload;
    try {
    //Downloding data asynchronously
        bytes = await webClient.DownloadDataTaskAsync (url);
    } catch (OperationCanceledException) {
        Console.WriteLine ("Task Canceled!");
    return;
    } catch (Exception e) {
        Console.WriteLine (e.ToString ());
    return;
    }
    //Storing the downloaded file in the local directory
    string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
    string localFilename = "downloaded.png";
    string localPath = Path.Combine (documentsPath, localFilename);
    FileStream fs = new FileStream (localPath, FileMode.OpenOrCreate);
    await fs.WriteAsync (bytes, 0, bytes.Length);
    Console.WriteLine ("localPath:" + localPath);
    //Resizing image is time costing, using async to avoid blocking the UI thread
    UIImage image = null;
    CGSize imageViewSize = imageView.Frame.Size;
    await Task.Run (() => {
    image = UIImage.FromFile (localPath).Scale (imageViewSize);
    });
    Console.WriteLine ("Loaded!");
    imageView.Image = image;
    this.downloadBtn.TouchUpInside -= cancelDownload;
    this.downloadBtn.TouchUpInside += downloadAsync;
    this.downloadBtn.SetTitle ("Download", UIControlState.Normal);
    this.progressView.Progress = 0.0f;
}
void HandleDownloadProgressChanged (object sender, DownloadProgressChangedEventArgs e)
{
    this.progressView.Progress = e.ProgressPercentage / 100.0f;
}
void cancelDownload (object sender, System.EventArgs ea)
{
    Console.WriteLine ("Cancel clicked!");
    if (webClient != null)
    webClient.CancelAsync ();
    webClient.DownloadProgressChanged -= HandleDownloadProgressChanged;
    this.downloadBtn.TouchUpInside -= cancelDownload;
    this.downloadBtn.TouchUpInside += downloadAsync;
    this.downloadBtn.SetTitle ("Download", UIControlState.Normal);
    this.progressView.Progress = 0.0f;
    new UIAlertView ("Canceled"
    , "Download has been canceled."
    , null
    , "OK"
    , null).Show ();
}

Output:


Image 1



Image 2



Image 3



Enjoy Coding...