简体   繁体   English

重构同步应用程序以使用异步/等待(C#)时遇到问题

[英]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. 我正在尝试将现有的同步应用程序重构为使用Async / Await的应用程序。 This WPF app was written originally using a BackgroundWorker thread calling a bunch of synchronous methods. 该WPF应用最初是使用BackgroundWorker线程编写的,该线程调用了一堆同步方法。 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 . 我走到了最深的层次,并逐步向上,将await.Task.Run((...))转换为异步方法,其中一些方法似乎用时不

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: 我想传递一个IProgress参数,以便能够将反馈反馈到UI中-最后一种最深的方法(执行时间最长的方法)是这样编写的:

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: 现在,如果我像这样在UI端调用CreateObjectAndSaveToFile():

await CreateObjectAndSaveToFile();

I get the desired effect - UI is responsive and files get saved one by one (can be 10-20 files). 我得到了预期的效果-UI具有响应能力,文件被一张一张保存(可以是10-20个文件)。 But for completeness, I'd like to add a progress bar to this (and therefore adding that IProgress parameter all the way down). 但是为了完整起见,我想为此添加一个进度条(并因此一直添加IProgress参数)。

I'm not sure how I can do that. 我不确定该怎么做。

You mention in the comments that you know how to use IProgress already. 您在评论中提到已经知道如何使用IProgress 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. 因此,如果您希望在每个任务完成时报告进度,则可以使用WhenAny()而不是WhenAll() ,并在完成时从列表中将其删除。 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 如果您想阅读更多信息,Microsoft文档实际上有一篇完整的文章: 启动多个异步任务并在完成时对其进行处理

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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