重构同步应用以使用 async/await (C#) 时遇到问题



我正在尝试将现有的同步应用程序重构为使用Async/Await的应用程序。此 WPF 应用最初是使用调用一组同步方法的 BackgroundWorker 线程编写的。我深入到最深的层次,然后努力向上,将这些方法转换为异步,对其中一些似乎没有花费太长时间的方法使用 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 参数(。

我不确定我该怎么做。

您在评论中提到您已经知道如何使用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文档实际上有一整篇关于此的文章: 启动多个异步任务并在它们完成时处理它们

最新更新