强制同步响应式扩展调用
本文关键字:扩展 调用 响应 同步 | 更新日期: 2023-09-27 18:14:51
我正在编写一些代码,看起来像这样:
public class ManagerViewModel : ManagerViewModelBase
{
public ManagerViewModel(ISettingsProvider settingsProvider):
base(settingsProvider.Settings)
}
public class ManagerViewModelBase
{
private IEnumerable<string> _mySettings = Enumerable.Empty<string>();
public ManagerViewModelBase(IEnumerable<string> settings)
{
_mySettings = settings;
}
}
ISettingsProvider是通过Unity提供的,看起来像:
public class SettingsProvider : ISettingsProvider
{
private readonly Service _service;
IEnumerable<string> _settings = Enumerable.Empty<string>();
public IEnumerable<string> Settings {get {return _settings}};
public SettingsProvider (
IService _service,
ISettingsProvider settingsProvider)
{
_service = service;
LoadSettings();
}
private void LoadSettings()
{
//_service just supplies the data
_service.GetSettings.Subscribe(LoadSettingsCompleted);
}
private void LoadSettingsCompleted(IEnumerable<string> settings)
{
_settings = settings;
}
}
问题是,当SettingsProvider实例化时,可能需要一点时间才能从服务调用中获得结果,因此,在调用完成并填充_settings之前,进行了基本(SettingsProvider . settings)调用,基本上传递了一个空枚举。
是否有一种方法可以使SettingsProvider。属性调用等待,直到数据从服务返回。GetSettings调用是可用的,并且在一定的时间后超时?我想我正在寻找最简单的方法来阻止这个属性调用。
谢谢。
我意识到你的问题是如何等待/阻塞,但我必须告诉你,你可能不应该。很可能你的ViewModel是在UI线程中创建的,阻塞是你想要的最后一件事。
如果你的ViewModel依赖于一些异步的东西,那么它的创建是异步的,你应该用等待隐藏它。不能使用Async in构造函数,但是你可以将你的VM构造函数设为私有,并公开一个Async静态工厂方法,比如:
private ManagerViewModel(IEnumerable<string> settings) : base(settings) {}
public async Task<ManagerViewModel> CreateAsync(ISettingsProvider settingsProvider) {
var settings = await settingsProvider.GetSettingsAsync();
return new ManagerViewModel(settings);
}
// ....
public async Task<IEnumerable<Settings>> GetSettingsAsync() {
return await _service.GetSettings().Timeout(...).FirstAsync();
}
我的建议是始终使用async并且永远不要阻塞。
这些都不是很反应性,但是您可以阻止使用Observable.FirstAsync()
和Observable.Wait()
扩展方法。所以你的LoadSettings()
方法看起来像这样:
private void LoadSettings()
{
_settings = _service.GetSettings
.Timeout(_expireTime, Observable.Return(Enumerable.Empty<string>()))
.FirstAsync()
.Wait();
_service.GetSettings.Subscribe(LoadSettingsCompleted);
}