Task<T>.ContinueWith
具有与 相同的基本基本概念IObservable<T>.Subscribe
。它们与 Reactive Extension 非常相似,可以提供转换扩展方法。由于IObservable<T>
是 BCL 的一部分,因此没有理由不实施IObservable<T>
. Task<T>
那么,不执行的原因是什么IObservable<T>
?
4 回答
Rx 团队在他们的 2.0 beta 博客文章中很好地涵盖了这一点。这是一个巨大的帖子,虽然里面有很多很棒的信息。
preemptive tl;dr = IObservable 用于未来结果序列,Task 用于单个未来结果
我认为最能解释这种关系的图表在那个帖子中,但不幸的是,它离得很远(正如我提到的,这是一个非常大的帖子:)
虽然整篇文章都值得一读(恕我直言),但有关 Rx/Task/async/await 如何组合在一起的相关文本从标题“Rx v2.0 和 .NET 4.5 “async”/“await”开始——更好的结合故事”
我只能猜测,但我认为有一些很好的理由:
Task<T>
并且IObservable<T>
实际上没有相同的基本概念。是的,两者都是异步的,但这几乎是所有共性结束的地方。两者之间的最大区别在于,它Task<T>
始终只有一个值,IObservable<T>
可以有尽可能多的值(或尽可能少,包括零)。如果已
Task<T>
实现IObservable<T>
,则类似于T
.Net 中的每个已实现IEnumerable<T>
,返回单个结果,即对象本身。转换
Task<T>
为IObservable<T>
. 要么使用Rx的ToObservable()
扩展方法,要么自己编写。这使得你所要求的变得不那么必要了。
我希望引用 MSFT (*) 的 Stephen Toub 的话是恰当的:
ParallelExtensionsExtras Tour - #2 - Task.ToObservable MSDN 博客文章:
事实证明,虽然目前
Task<TResult>
没有实现,但实际上非常适合这样做。一个 observable 代表任意数量的由流的结尾或异常终止的值。A符合此描述:它以单个值或异常完成。虽然 .NET Framework 的未来版本可能会实现,但我们现在可以通过将其实现为 ; 的扩展方法来获得相关行为;事实上,Rx就包含了这样一个扩展方法,就像IObservable<T>
Task<TResult>
Task<TResult>
IObservable<T>
Task<TResult>
ParallelExtensionsExtras
(*) 不知道“FT”是什么意思,除了 MSFT 是纳斯达克股票代码,意思是 MS,但“MSFT”中的“MS”肯定是指微软
原因是,虽然Task<T>
类型在 .NET 框架中,但 Reactive Extensions (Rx) 并IObservable<T>
没有。该System.Reactive
程序集具有System.Threading.Tasks
依赖项,因此后者中的任何内容都不能引用前者。
如果并且当他们将 Rx 添加到 .NET 时,他们可能会按照您的建议进行操作。
编辑:
实际上,我可能说得太快了。查看文档。看来该IObservable<T>
接口实际上存在于mscorlib
.NET 4 和 4.5 的程序集中。所以我上面说的并不是一个完全正当的理由。我正在将我的猜测原因修改为“因为他们还没有将 Rx 集成到 .NET 中”,而不是“由于循环依赖,目前不可能”。