0

I have to download and save lot of images to local folder. Also I have to update UI while downloading images. Now I am using the following code to download images one by one. But the problem is UI getting blocked on each download request. How should I handle download method? I don't know much about threading. Can anyone help me with a good method?

public async Task<T> ServiceRequest<T>(string serviceurl, object request)
{
    string response = "";
    httpwebrequest = WebRequest.Create(new Uri(serviceurl)) as HttpWebRequest;
    httpwebrequest.Method = "POST";

    httpwebrequest.ContentType = "application/json";
    byte[] data = Serialization.SerializeData(request);

    using (var requestStream = await Task<Stream>.Factory.FromAsync(httpwebrequest.BeginGetRequestStream, httpwebrequest.EndGetRequestStream, null))
    {
        await requestStream.WriteAsync(data, 0, data.Length);
    }

    response = await httpRequest(httpwebrequest);

    var result = Serialization.Deserialize<T>(response);
    return result;
}


public async Task<string> httpRequest(HttpWebRequest request)
{
    try
    {
        string received;

        using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
        {
            using (var responseStream = response.GetResponseStream())
            {
                using (var sr = new StreamReader(responseStream))
                {
                    received = await sr.ReadToEndAsync();
                }
            }            
            response.Close();
        }

        return received;
    }
    catch(Exception ex)
    {
        return "";
    }
}
J. Steen
  • 15,470
  • 15
  • 56
  • 63
Sachin123
  • 251
  • 5
  • 18

1 Answers1

3

I would recommend you to use the System.Net.Http.HttpClient. You could get it from the Nuget, just select the search option to include the pre-release channel as well. There's one catch though: it's not officially released yet, so you cannot use it in production code right now. And there's no word on when it will be finally released. But if you're just learning, you could use it freely. And it make things like you describe very straightforward. Here's a sample from my code, which, by a happy coincidence :), does exactly what you want:

private IEnumerable<string> CountPictures(int from, int to, string folder)
{
    for (int i = from; i < to; i++)
        yield return string.Format("{0}/image{1}.jpg", folder, i.ToString("D2"));
}

private async Task ImportImages()
{
    HttpClient c = new HttpClient();
    int count = 0;
    c.BaseAddress = new Uri("http://www.cs.washington.edu/research/imagedatabase/groundtruth/", UriKind.Absolute);
    foreach (var pic in CountPictures(1, 48, "leaflesstrees"))
    {
        var pic_response = await c.GetAsync(pic, HttpCompletionOption.ResponseContentRead);
        if (pic_response.IsSuccessStatusCode)
        {
            await SaveImageAsync(pic.Replace('/', '_'), await pic_response.Content.ReadAsStreamAsync());
            Debug.WriteLine(pic + " imported");
            count++;
        }
    }           
    Debug.WriteLine(string.Format("{0} images imported", count));
}

private Task SaveImageAsync(string filename, Stream stream)
{
    var task = Task.Factory.StartNew(() =>
    {
        if (stream == null || filename == null)
        {
            throw new ArgumentException("one of parameters is null");
        }
        try
        {
            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream targetStream = isoStore.OpenFile(filename, FileMode.Create, FileAccess.Write))
                {
                    byte[] readBuffer = new byte[4096];
                    int bytesRead = -1;
                    stream.Position = 0;
                    targetStream.Position = 0;

                    while ((bytesRead = stream.Read(readBuffer, 0, readBuffer.Length)) > 0)
                    {
                        targetStream.Write(readBuffer, 0, bytesRead);
                    }
                }
            }
        }
        catch (Exception e)
        {
            System.Diagnostics.Debug.WriteLine("DocumentStorageService::LoadImage FAILED " + e.Message);
        }
    });
    return task;
}

In order to display an image from Isolated Storage then, you could refer to one of the approaches described in my answer here.

Community
  • 1
  • 1
Haspemulator
  • 11,050
  • 9
  • 49
  • 76
  • Thank you for your suggestion. But i have to release my application very soon.So can you suggest any other method? – Sachin123 Apr 22 '13 at 10:16