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

时间:2019-08-12 17:09:14

标签: c# asynchronous async-await

我正在尝试将现有的同步应用程序重构为使用Async / Await的应用程序。该WPF应用最初是使用BackgroundWorker线程编写的,该线程调用了一堆同步方法。我走到了最深的层次,然后向上工作,在其中一些似乎不是taking too long的地方使用await Task.Run(()..)将这些方法转换为异步方法。

尽管如此,我仍然坚持。我想传递一个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);
}

现在,如果我像这样在UI端调用CreateObjectAndSaveToFile():

await CreateObjectAndSaveToFile();

我得到了预期的效果-UI响应并且文件被一个接一个地保存(可以是10-20个文件)。但是为了完整起见,我想为此添加一个进度条(并因此一直添加IProgress参数)。

我不确定该怎么做。

1 个答案:

答案 0 :(得分:0)

您在评论中提到已经知道如何使用IProgress。因此,如果您希望在每个任务完成时报告进度,可以使用WhenAny()而不是WhenAll(),并在完成时从列表中将其删除。像这样:

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

    SaveFileTaskArray.Remove(finishedTask);

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

如果您想了解更多信息,Microsoft文档实际上有整篇文章:Start Multiple Async Tasks and Process Them As They Complete