简体   繁体   中英

Having trouble refactoring synchronous app to use async/await (C#)

I'm trying to refactor an existing synchronous app into one that uses Async/Await. This WPF app was written originally using a BackgroundWorker thread calling a bunch of synchronous methods. I went down to the deepest level and worked my way up, converting these methods to async, using await Task.Run(()..) on some of them that didn't seem to be taking too long .

I am stuck on something though. I want to pass in an IProgress parameter, to be able to get feedback into the UI -- and the last, deepest method, the one that takes the longest to execute, is written this way:

public static Task<bool> SaveToFileAsync(string filePath)
{
    return Task.Run(() => SaveToFile(filePath));

    /*
        SaveToFile calls into an unmanaged dll that uses a few loops and writes
        to file using fopen/fwrite...
    */
}

private async void CreateObjectAndSaveToFile(/*IProgress progress*/)
{
    List<Task> SaveFileTaskArray = new List<Task>();
    int index = 0;

    foreach (...)
    {
        // 
        {
            DoSomethingThatTakesSomeTime();
            //Start Async Task to save this SomeThing to file
            SaveFileTaskArray.Add(SaveToFileAsync(fileName));
        }
        index++;
    }

    await Task.WhenAll(SaveFileTaskArray);
}

Now if I call CreateObjectAndSaveToFile() on the UI side like so:

await CreateObjectAndSaveToFile();

I get the desired effect - UI is responsive and files get saved one by one (can be 10-20 files). But for completeness, I'd like to add a progress bar to this (and therefore adding that IProgress parameter all the way down).

I'm not sure how I can do that.

You mention in the comments that you know how to use IProgress already. So if you want report progress as each task finishes, you can use WhenAny() instead of WhenAll() , and remove each task from the list as it finishes. Something like this:

while (SaveFileTaskArray.Count > 0) {
    var finishedTask = await Task.WhenAny(SaveFileTaskArray);

    SaveFileTaskArray.Remove(finishedTask);

    //Report progress of how many are left
    progress.Report(SaveFileTaskArray.Count);
}

The Microsoft documentation actually has a whole article about this, if you want to read more: Start Multiple Async Tasks and Process Them As They Complete

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM