我有一种方法需要200毫秒才能运行,因此希望将结果缓存。此结果将被频繁使用,但永远不会改变。
我不确定是否最好的解决方案是什么,我应该将其放在属性或get方法上吗?
例如:
1
private string _result;
public string Result => _result ?? (_result = GetSlowResult());
2
private string _result;
public string GetResult() => _result ?? (_result = GetSlowResult());
就个人而言,我通常希望它从“现在”而不是“以后”可用,但是使用Get方法,我希望结果总是检索新鲜的GetSlowResult
而不是使用缓存的值。我可以将方法名称更改为GetCachedResult
,但是我也没有因此而出售,因为那样看来您首先需要调用GetResult
方法。
对此有任何指导原则吗?你喜欢什么?
答案 0 :(得分:1)
我建议您使用Lazy<T>
类。它使您通过一个讨论如何创建该对象的工厂,此后,仅在您第一次请求该对象时才创建该对象,然后使用相同的引用(缓存的值)。
这是它的外观:
Lazy<T> Result = new Lazy<T>(GetSlowResult); //T is your type
然后,要使用结果,只需获取她的财产Value
:
T myResult = Result.Value;
您可以在official dotnet docs中查看有关此内容的更多信息。
答案 1 :(得分:0)
我将使用只读属性和填充该属性的方法来完成此操作。
如果您知道需要此结果,则可以在开始时将其加载-在启动服务,激活ov视图等过程中。
我在WPF应用程序中大多使用ReactiveUI,因此看起来像这样:
// ViewModel constructor
GetResult = ReactiveCommand.CreateFromTask(async () => _model.GetResultAsync()); // notice that method is async
// there is also overload with CancelationToken
_result = GetResult.Retry(3).ToProperty(this, x => x.Result); // we can retry few times and we get change notification
GetResult.Subscribe(result =>{
// do something as soon as the result is loaded
});
GetResult.ThrownExceptions.Subscribe( errorHandler);
// ViewModel properties
private ObservableAsProperetyHelper<ResultType> _result;
public ResultType Result => _result.Value;
// view constructor
this.WhenActivated(d =>{ // d is CompositeDisposable for cleanup
ViewModel.GetResult.Execute().Subscribe().DisposeWith(d); // cancel command if the view is deactivated before it's finished
});
这样,您可以在适当的时候进行异步调用,并将结果存储以备后用。您还可以轻松刷新结果-单独使用惰性属性时,结果会变得很脏。
另一方面,您可以轻松创建加载微调器:
_isBusy = GetResult.IsExecuting.ToProperty(this, x => x.IsBusy);
我在始终在后台运行自定义HTTP服务器的Windows服务中遵循此模式。如果要在特定时刻强制加载,可以await GetResult.Execute()
。
在我的实践中,这种模式显示的缺点很少-主要是样板代码,但是使用适当的工具,它可以非常快地编写。
如果您正在创建某种服务类型的应用程序,控制台或其他内容,则MVVM模式仍然非常有用,您只是不执行视图。