【问题标题】:Exception 'Sequence contains no elements' upon awaiting observable等待可观察时出现异常“序列不包含元素”
【发布时间】:2019-03-29 15:13:05
【问题描述】:

我正在使用System.Reactive.Linq 扩展方法将可观察对象转换为异步方法中的结果。当我有对象引用时,代码可以正确运行;但是,当我将 null 传递给 OnNext 方法时,生成的等待者会抛出

System.InvalidOperationException
 HResult=0x80131509
 Message=Sequence contains no elements.
 Source=System.Reactive
 StackTrace:
  at System.Reactive.Subjects.AsyncSubject`1.GetResult() in D:\a\1\s\Rx.NET\Source\src\System.Reactive\Subjects\AsyncSubject.cs:line 441
  at <namespace>.DataServiceTests.<GetWithInvalidIdShouldReturnNull>d__5.MoveNext() in <local test code>

我期望等待者得到一个空值。我的测试如下:

[Fact]
public async void GetWithInvalidIdShouldReturnNull()
{
    var testId = shortid.ShortId.Generate();
    var result = await myTestOjbect.GetById(testId);
    Assert.Null(result);
}

GetById 方法是:

public IObservable<object> GetById(string id)
{
    return Observable.Create((IObserver<object> observer) => {
        var item = this._repository.Get(id);  // This returns null when id is not found in collection
        observer.OnNext(item);
        observer.OnCompleted();
        return Disposable.Empty;
    });
}

【问题讨论】:

  • 我确实发现在GetbyId(testId) 的末尾添加SingleOrDefaultAsync() 可以按预期工作,但为什么呢?
  • 观察者的 OnNext() 如何处理空值?
  • 如果这是一个错误状态,observable 应该发送 OnError,而不是 OnNext。观察者期望在 OnNext 中接收有效对象。
  • 如果_repository.Get(id) returns nullawait myTestOjbect.GetById 应该返回null。您使用的是哪个版本的 Rx?
  • @clay - 在这种特殊用法中,null 比异常更可取。 @mm8 - System.Reactive 4.1.3

标签: c# .net-core system.reactive


【解决方案1】:

这里是您的错误被抛出的地方: https://github.com/dotnet/reactive/blob/master/Rx.NET/Source/src/System.Reactive/Subjects/AsyncSubject.cs#L441

您的主题似乎没有任何观察者,或者观察者已被释放。

【讨论】:

  • 放置“await”会创建一个观察者并订阅可观察对象。我认为这更多地与它不接受 null 作为其他地方的值这一事实有关,而且我已经在一定程度上得出了这个结论。
  • 认为可能是因为我收到相同的错误(即“序列不包含元素”)而没有传递 null ,所以 observable 已被处理。源代码表明这是原因。对我来说,解决方法是在 ToNext 调用之后省略对 OnCompleted 的调用。
【解决方案2】:

虽然我是在 Linqpad 中完成的,但对我来说效果很好。这是我的代码:

async Task Main()
{
    var result = await GetById("");
    if(result == null)
        Console.WriteLine("OK!");
    else
        throw new Exception("Expected Null!");

}

public IObservable<object> GetById(string id)
{
    var o = Observable.Create<object>(obs =>
    {
        obs.OnNext(null);
        obs.OnCompleted();
        return Disposable.Empty;
    });

    return o;
}

【讨论】:

  • 您使用的是不同版本的 Rx 和/或 .net 吗? Nuget 显示我最新。
  • 我检查了版本。 4.1.3,Rx.net.
  • 当你运行我打印的示例代码时,它有效吗?
  • 我确实尝试将repository.get 的行更改为空,然后,我发布了问题。所以令人费解的是为什么它对你有用,但对我不起作用。我在这里看到的唯一区别是&lt;object&gt; 的位置在哪里,但我会尝试一下
猜你喜欢
  • 1970-01-01
  • 2015-04-16
  • 2019-04-24
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
  • 1970-01-01
  • 2018-01-03
  • 1970-01-01
相关资源
最近更新 更多