C#.NET异步/等待报告进度而没有在任何地方传递IProgress?

时间:2018-11-16 04:25:57

标签: c# asynchronous progress

首先让我说我对C#完全陌生-我来自Java背景,在Java中我并没有做很多工作。

我创建了一个基本的Winforms应用程序,该应用程序具有几个按钮,这些按钮可以启动一些长时间运行的任务,这些任务本身可能具有也可能不具有运行时间不确定的一系列子任务。这些子任务包括API调用,下载文件以及文件数据中对象的映射。

在主表单上只有一个标签,以前可以通过从当前正在运行的任何函数直接访问它来进行更新,例如

labelProgress.Text = "Beginning main long running function"; 
myClient.LongRunningFunction(); //more methods called inside this function, which update the label directly
labelProgress.Text = "Long running function is complete";

显然,此问题是GUI被阻止(无法单击X按钮或四处移动窗口)。我知道这不是长时间运行的功能来更新GUI的“正确”方法。

现在就着手解决问题以及问题的根源-如何报告进度,以便从多个嵌套方法调用中更新标签,而无需在所有地方传递IProgress?我读过的所有示例的深度都为一-这意味着处理程序启动了一个任务,然后该任务直接报告进度,而无需移交给其他自己也需要报告进度的方法。

我基本上只想继续使用有意义的状态信息更新标签,以便可以看到正在发生的事情,但这似乎唯一的方法是将IProgress上下传递到每个方法调用中。有更好的方法吗?

这是我的顶级按钮事件处理程序

private async void buttonStart_Click(object sender, EventArgs e) 
{
    MyClient client = new MyClient();
    var progress = new Progress<String>(s => labelProgress.Text = s);
    await Task.Factory.StartNew(() => myClient.LongRunningFunction(progress), TaskCreationOptions.LongRunning);
}

然后在MyClient类中

public async Task LongRunningFunction(IProgress<String> progress)
{
    await apiGetter.getFiles(); //async call to download some files, might want to report progress inside here later too       
    progress.Report("Processing downloaded files");
    fileProcessor.processFiles(progress); //pass the IProgress here too?
}

最后是FileProcessor

public void processFiles(IProgress<String> progress) 
{
    //collect filenames from a predetermined location, churn through
    progress.Report("Working on file " + filename);
    doSomeStuffWithFileAndAlsoReportOnProgress(filename, progress); //again passing the IProgress down a level
    progress.Report("Done with " + filename);
}

1 个答案:

答案 0 :(得分:0)

此处是“进度属性”,用于生成带有PropertyChanged事件的报告。

它将解决IProgress依赖问题

  

没有在任何地方传递IProgress

public sealed class PropertyProgress<T> : IProgress<T>, INotifyPropertyChanged
{
      public PropertyProgress(T initialProgress = default(T));

      public T Progress { get; }

      public event PropertyChangedEventHandler PropertyChanged;
}