在C#中使用反应性扩展时如何显示进度 [英] How to do I show progress when using Reactive Extensions in C#

查看:97
本文介绍了在C#中使用反应性扩展时如何显示进度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Am在C#中使用反应性扩展来执行一些计算.到目前为止,这是我的代码的样子.我尝试将代码包装起来,以便在Calculate方法中执行一系列任务时可以显示进度

Am using reactive extensions in C# to perform some calculations. Here is how my code looks like so far. I have tried to wrap the code around so that I can show progress while to executing a series of tasks within my Calculate method

这是可观察的

IObservable<ResultWithProgress<SampleResult>> Calculate(){
  return Observable.Create<ResultWithProgress<SampleResult>>(obs => {
     var someTask = DoSomeTask1();
     obs.OnNext(new ResultWithProgress(){Progress = 25, ProgressText     ="Completed Task1"});
     var someOtherTask = DoSomeMoreTask();
     obs.OnNext(new ResultWithProgress(){Progress = 50, ProgressText ="Completed Task2"});
     var calcResult = DoSomeMoreTask2();
     obs.OnNext(new ResultWithProgress(){Progress = 75, ProgressText = "Completed Task3"});
     var calcResult = FinalCalc();
     obs.OnNext(new ResultWithProgress(){Progress = 100, ProgressText ="Completed Task4", Result = calcResult});
     obs.OnCompleted();
  }

}

结果类包装进度和结果

class ResultWithProgress<T>{
 public int Progress {get; set;}
 public Result T {get; set;}
 public string ProgressText {get; set;}
}

包含最终结果的结果对象 类SampleResult {}

Result object which contains the final result class SampleResult{}

用法:

Calculate().Subscribe(resultWithProgress => {
  if(resultWithProgress.Result == null) //Show progress using   resultWithProgress.Progress
  else // get the result
})

我某种程度上觉得这可能不是最好的方法.感觉很多次创建ResultWithProgress对象而没有Result的感觉似乎是一种代码味道,特别是如果我想在Calculate()内执行超过10个任务的时候

I somehow feel that this might not the best way to do it. It feels that creating ResultWithProgress object many times without the Result seems like a code smell, especially if I have more than 10 tasks that I want to do within my Calculate()

如果您能给我任何有关如何使用它的指示,或者我是否错误地解决了这个问题,我将不胜感激?

I would appreciate it if you can give me any pointers on how to use this or am I approaching this problem wrongly?

推荐答案

此答案使用了谜题答案讨论的相同原理.

This answer uses the same principles Enigmativity's answer discusses.

此版本使用Create的异步重载.

This version uses the async overload of Create.

它还利用.NET 4.5 IProgress 而不是原始的Action<T>来报告进度.

It also makes use of the .NET 4.5 IProgress instead of a raw Action<T> to report progress.

struct CalculationProgress
{
    public int Progress { get; private set; }
    public string ProgressText { get; private set; }

    public CalculationProgress(int progress, string progressText)
        : this()
    {
        Progress = progress;
        ProgressText = progressText;
    }
}

public IObservable<Result> Calculate(IProgress<CalculationProgress> progress)
{
    return Observable.Create<Result>((observer, cancellationToken) =>
    {
        // run the work on a background thread
        // so we do not block the subscriber
        // and thus the subscriber has a chance
        // to unsubscribe (and cancel the work if desired)
        return Task.Run(() =>
        {
            DoSomeTask1();
            cancellationToken.ThrowIfCancellationRequested();
            progress.Report(new CalculationProgress(25, "First task"));

            DoSomeTask2();
            cancellationToken.ThrowIfCancellationRequested();
            progress.Report(new CalculationProgress(50, "Second task"));

            DoSomeTask3();
            cancellationToken.ThrowIfCancellationRequested();
            progress.Report(new CalculationProgress(75, "third task"));

            var result = DoFinalCalculation();            
            cancellationToken.ThrowIfCancellationRequested();
            progress.Report(new CalculationProgress(100, "final task"));

            observer.OnNext(result);
        }, cancellationToken);
    });
}

这篇关于在C#中使用反应性扩展时如何显示进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆