计算进程逻辑应该驻留在服务层吗?



在我的WPF应用程序中,我的ViewModel与ViewModelService对话,后者又与例如CalculationService对话,以检索要在视图中显示的处理过的数据。我想为视图能够报告完成的百分比给用户。我的问题是双重的。

第一个问题是这个逻辑应该驻留在哪里?应该让CalculationService与实际结果一起报告进度,还是让ViewModel服务计算进度百分比细节?

第二,我看到我可以使用TPL或使用reactiveextensions来实现这一点。我倾向于响应式扩展,因为在我的情况下,计算服务的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流的"输出",因为他们到达,我也可以使用并行。Foreach获得性能

对此有什么想法吗?

谢谢凯

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

下面是我如何使用Rx:

首先创建一个Progress<T>类,将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);
            });     
}

相关内容

  • 没有找到相关文章

最新更新