在我的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);
});
}