强制同步无功扩展呼叫

时间:2015-09-28 20:56:29

标签: c# system.reactive

我正在研究一些看起来像这样的代码:

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之前,将调用base(settingsProvider.Settings)调用,基本上传递一个空的可枚举。

有没有办法让SettingsProvider.Settings属性调用等待来自Service.GetSettings调用的数据可用,并在一定时间后超时?我想我正在寻找阻止该属性调用的最简单方法。

感谢。

2 个答案:

答案 0 :(得分:0)

这些都不是被动,但您可以阻止使用Observable.FirstAsync()Observable.Wait()扩展方法。因此,您的LoadSettings()方法可能类似于:

private void LoadSettings()
{
    _settings = _service.GetSettings
                        .Timeout(_expireTime, Observable.Return(Enumerable.Empty<string>()))
                        .FirstAsync()
                        .Wait();
    _service.GetSettings.Subscribe(LoadSettingsCompleted);
}

答案 1 :(得分:0)

我意识到你的问题是如何等待/阻止,但我必须告诉你,你可能不应该。可能你的ViewModel是在UI线程中创建的,阻塞是你想要的最后一件事。

如果你的ViewModel依赖异步的东西,那么它的创建是异步的,你应该用等待隐藏它。 不能使用构造函数中的异步,但也可以将VM构造函数设置为私有,并公开异步静态工厂方法,例如:

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();
}

一直暴露异步,永远不会阻止我的建议。