Windows Store Apps, download multiple files with threads

271 views Asked by At

I have this following method that I use to download a file's content:

public async Task<String> DownloadFileService(String filePath, string id)
{
    string resposta = string.Empty;
    try
    {
        using (var httpClient = new HttpClient { BaseAddress = Constants.baseAddress })
        {
            string token = App.Current.Resources["token"] as string;
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

            string fname = Path.GetFileName(filePath);
            string path = Path.GetDirectoryName(filePath);
            path = path.Replace(fname, "");
            StorageFolder folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(Constants.DataDirectory + "\\" + path, CreationCollisionOption.OpenIfExists);

            StorageFile imgFile = await folder.CreateFileAsync(fname, CreationCollisionOption.ReplaceExisting);

            using (var response2 = await httpClient.GetAsync("file?fileId=" + id))
            {

                Stream imageStream = await response2.Content.ReadAsStreamAsync();
                byte[] bytes = new byte[imageStream.Length];

                imageStream.Read(bytes, 0, (int)imageStream.Length);


                await FileIO.WriteBytesAsync(imgFile, bytes);
                resposta = Convert.ToBase64String(bytes);
            }

        }
        return resposta;
    }
    catch (Exception e)
    {
        Debug.WriteLine(e.Message);
    }
}

I would like to know how I can call this multiple times to download several files at same time and wait until all files are downloaded, then do other stuff.

EDIT

After this suggestion I tried creating the following method:

public async void checkFilesExist(JsonArray array, string path)
{
    List<Document> list = new List<Document>();
    ObjectsService obj = new ObjectsService();
    List<Task> ts = new List<Task>();

    foreach (var item in array)
    {
        JsonObject newDoc;
        JsonObject.TryParse(item.Stringify(), out newDoc);

        if (newDoc.ContainsKey("libraryType") || !newDoc.ContainsKey("fileName"))
            continue;
        string name = newDoc["fileName"].GetString();
        string id = newDoc["_id"].GetString();
        File file = new File(name);
        file.id = id;
        Document doc = file;
        doc.Parent = Document.FromPath(path);

        path = path.Replace("/", "\\");
        StorageFolder folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(Constants.DataDirectory + "\\" + path, CreationCollisionOption.OpenIfExists);
        try
        {
            await folder.GetFileAsync(file.Name);
        }
        catch (Exception e)
        {
            list.Add(doc);
            Task x = obj.DownloadFileService(doc.GetFullPath(), file.id);
            ts.Add(x);
            Debug.WriteLine(" Ex: " + e.Message);
        }
    }
    try
    {
        Task.WaitAll(ts.ToArray());
        Debug.WriteLine("AFTER THrEADS");
    }
    catch (Exception e)
    {
        Debug.WriteLine("Ex2:  " + e.Message);
    }
}

What this does is, with a response in json I get from a webservice listing some files, I check if they already exist in localfolder. If they don't I call the method I had at start of the question.

I then have a list of tasks, and I add the call of the DownloadFileService() as a new task in the list, after that I do the Task.WaitAll() to wait for the downloads to finish.

Using fiddler I see the downloads all start, but for some reason my code doesn't stop at Task.WaitAll(), it just keeps going and it starts to use the files that are still being downloaded, creating a bunch of problems :D

2

There are 2 answers

0
Hamid Pourjam On BEST ANSWER

you can use Task.WaitAll. It waits for all of the provided Task objects to complete execution.

var t1 = DownloadFileService("file1", "1");
var t2 = DownloadFileService("file2", "2");
var t3 = DownloadFileService("file3", "3");

Tasks.WaitAll(t1, t2, t3);
4
Kevorkian On

Or you can use :

await  DownloadFileService("Path", "id");
await  DownloadFileService("Path", "id");
await  DownloadFileService("Path", "id");
await  DownloadFileService("Path", "id");