【问题标题】:Should Calculation Progress logic reside on Service Layer?计算进度逻辑是否应该驻留在服务层上?
【发布时间】:2015-08-06 20:42:37
【问题描述】:

在我的 WPF 应用程序中,我的 ViewModel 与 ViewModelService 对话,ViewModelService 反过来与 CalculationService 对话,以检索要在 View 中呈现的已处理数据。我希望视图能够向用户报告完成百分比。我的问题有两个。

首先是这个逻辑应该放在哪里? CalculationService 是否应该负责报告进度以及实际结果,或者 ViewModel 服务是否计算进度百分比详细信息。

其次,我发现我可以使用 TPL 或使用 ReactiveExtentions 来实现这一点。我倾向于响应式扩展,因为在我的情况下,计算服务的 API 和实现看起来像这样

//This is pseudo code, just aiming to show my intention here
    IEnumerable<Output> Calculate(IEnumerable<Inputs> inputs){
             List<Output> output = new List<Output>();
             foreach(var input : inputs){
               //long running calculation, which produces output
               //outputs.Add(output)
             }
           }

我假设如果我沿着 Reactive 路线走,我可以使用 Reactive 的 OnNext 在它们到达时流式传输“输出”,并且我还可以使用 Parallel.Foreach 来获得性能。

对此有何想法或想法?

谢谢 凯

【问题讨论】:

    标签: c# task-parallel-library system.reactive


    【解决方案1】:

    我认为视图模型层可以计算进度。

    这是我使用 Rx 的方法:

    首先创建一个Progress&lt;T&gt; 类,将Output 提升为可以报告自己进度的类型。

    public class Progress<T>
    {
        public Progress(T value, int current, int total)
        {
            this.Value = value;
            this.Current = current;
            this.Total = total;
        }
        public T Value { get; private set; }
        public int Current { get; private set; }
        public int Total { get; private set; }
        public double Percentage
        {
            get
            {
                return (double)this.Current / (double)this.Total;
            }
        }
    }
    

    现在您只需要Calculate 方法。

    public IObservable<Progress<Output>> Calculate(IEnumerable<Inputs> inputs)
    {
        return
            Observable
                .Create<Progress<Output>>(o =>
                {
                    var source = inputs.ToArray();
                    var total = source.Length;
                    return
                        source
                            .ToObservable()
                            .Select((x, n) =>
                                new Progress<Output>(LongRunningCalculation(x), n, total))
                            .Subscribe(o);
                });     
    }
    

    这并没有带来任何性能改进,但我当然不会使用Parallel.ForEach 来获得任何改进。混合任务、可枚举和可观察对象并不是最好的。坚持一种范式总是更好。

    下面是我如何让它并行运行。

    IObservable<Progress<Output>> Calculate(IEnumerable<Inputs> inputs)
    {
        return
            Observable
                .Create<Progress<Output>>(o =>
                {
                    var source = inputs.ToArray();
                    var total = source.Length;
                    return
                        source
                            .ToObservable()
                            .SelectMany(x => Observable.Start(() => LongRunningCalculation(x)))
                            .Select((x, n) => new Progress<Output>(x, n, total))
                            .Subscribe(o);
                });     
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 2011-07-01
      • 2010-10-10
      • 2012-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多