我只想学习它们以及如何将它们结合使用。我知道它们可以互相补充,但我找不到有人真正做到这一点的例子。
我只想学习它们以及如何将它们结合使用。我知道它们可以互相补充,但我找不到有人真正做到这一点的例子。
Task<T>
、IObservable<T>
、Nullable<T>
、IEnumerable<T>
、Lazy<T>
等,它们为底层类型T
提供特殊能力。Task<T>
来表示单个值T
的异步计算。IObservable<T>
来表示零个或多个值T
的异步计算。Task
类型来表示异步执行Action
lambda,但这可以视为Task<T>
的特殊情况,其中T
为void
。就像C#中的标准方法返回void
一样:public void MyMethod() { }
Rx还可以使用一种称为Unit
的特殊类型来处理同样的特殊情况。
TPL和Rx之间的区别在于返回值的数量。TPL只有一个,而Rx是零个或多个。
因此,如果您通过仅使用返回单个值的可观察序列来特别处理Rx,则可以以类似于TPL的方式进行一些计算。
例如,在TPL中,我可以编写:
Task.Factory
.StartNew(() => "Hello")
.ContinueWith(t => Console.WriteLine(t.Result));
Observable
.Start(() => "Hello")
.Subscribe(x => Console.WriteLine(x));
我可以通过指定TPL来执行计算,从而在Rx中更进一步:
Observable
.Start(() => "Hello", Scheduler.TaskPool)
.Subscribe(x => Console.WriteLine(x));
默认情况下,线程池被使用。
现在我可以进行一些“混搭”。如果我添加一个对 System.Reactive.Threading.Tasks
命名空间的引用,我就可以轻松地在任务和可观察对象之间切换。
Task.Factory
.StartNew(() => "Hello")
.ToObservable()
.Subscribe(x => Console.WriteLine(x));
Observable
.Start(() => "Hello")
.ToTask()
.ContinueWith(t => Console.WriteLine(t.Result));
ToObservable()
和.ToTask()
的调用以及从一个库到另一个库的翻转。.ToArray()
扩展方法将多个序列值转换为单个数组值,然后将其转换为任务。就像这样:Observable
.Interval(TimeSpan.FromSeconds(1.0))
.Take(5) // is IObservable<long>
.ToArray()
.ToTask() // is Task<long[]>
.ContinueWith(t => Console.WriteLine(t.Result.Length));
我认为这是对你问题的一个相当基础的回答。这是否符合你的期望?
Task<void>
。 - svickDataFlow
。很抱歉没有回答你的问题。 - EnigmativityTask<void>
是 IObservable<Unit>
所要表示的。你不能使用 Task<Unit>
来代替 Task<void>
吗? - EnigmativityUnit
的函数末尾明确地return Unit.Default;
。 - svick