【问题标题】:Having trouble refactoring synchronous app to use async/await (C#)在重构同步应用程序以使用 async/await (C#) 时遇到问题
【发布时间】:2019-08-13 03:36:42
【问题描述】:

我正在尝试将现有的同步应用程序重构为使用 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 参数)。

我不知道该怎么做。

【问题讨论】:

  • 您是否尝试过传递一些回调或事件,然后从高层监听该事件或回调?
  • 参见this answer(非常简单,与您已有的代码相似)及其副本,它使用专有实现。还有许多其他示例。
  • 谢谢。我知道如何使用 IProgress,但这不是问题所在。问题是最后(即使那里有一个循环),我正在等待一个 Task.WhenAll,并且我没有指示何时完成单个保存任务。
  • 然后修改SaveToFile(filePath),以便您可以从那里更新IProgress。您在这里有一个并行的进度,您可以更新每个文件的进度+1,将进度最大值设置为您要复制的文件数。我不知道DoSomethingThatTakesSomeTime(); 在做什么,需要更多时间才能完成以及您要通知的进度。如果最终的文件复制操作足够了,那就去吧。

标签: c# asynchronous async-await


【解决方案1】:

您在 cmets 中提到您已经知道如何使用 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

【讨论】:

  • 请注意,这种技术不适用于大量任务。当任务超过 3,000 个左右时,您将获得大量开销。
猜你喜欢
  • 2018-08-21
  • 2018-12-05
  • 2020-12-11
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-19
  • 2019-10-30
相关资源
最近更新 更多