好的,试着去理解Rx,有点迷失在这里。
现在不推荐使用FromAsyncPattern,所以我从here(使用Rx的Light up Task部分)中获取了示例,并且它可以工作,我只做了一些更改,而不是使用等待,只需等待observable和订阅...... ..
我不明白为什么称为SumSquareRoots函数的两倍?
var res = Observable.FromAsync(ct => SumSquareRoots(x, ct))
.Timeout(TimeSpan.FromSeconds(5));
res.Subscribe(y => Console.WriteLine(y));
res.Wait();
class Program
{
static void Main(string[] args)
{
Samples();
}
static void Samples()
{
var x = 100000000;
try
{
var res = Observable.FromAsync(ct => SumSquareRoots(x, ct))
.Timeout(TimeSpan.FromSeconds(5));
res.Subscribe(y => Console.WriteLine(y));
res.Wait();
}
catch (TimeoutException)
{
Console.WriteLine("Timed out :-(");
}
}
static Task<double> SumSquareRoots(long count, CancellationToken ct)
{
return Task.Run(() =>
{
var res = 0.0;
Console.WriteLine("Why I'm called twice");
for (long i = 0; i < count; i++)
{
res += Math.Sqrt(i);
if (i % 10000 == 0 && ct.IsCancellationRequested)
{
Console.WriteLine("Noticed cancellation!");
ct.ThrowIfCancellationRequested();
}
}
return res;
});
}
}
答案 0 :(得分:12)
这两次调用SumSquareRoots的原因是因为你订阅了两次:
// Subscribes to res
res.Subscribe(y => Console.WriteLine(y));
// Also Subscribes to res, since it *must* produce a result, even
// if that result is then discarded (i.e. Wait doesn't return IObservable)
res.Wait();
Subscribe
是Rx的foreach
- 就像你foreach
IEnumerable
两次一样,你最终可以完成2倍的工作,多个Subscribe
s意味着多项工作。要撤消此操作,您可以使用不会丢弃结果的阻止调用:
Console.WriteLine(res.First());
或者,您可以使用Publish
“冻结”结果并将其播放回&gt; 1个订阅者(有点像你在LINQ中使用ToArray
的方式):
res = res.Publish();
res.Connect();
// Both subscriptions get the same result, SumSquareRoots is only called once
res.Subscribe(Console.WriteLine);
res.Wait();
您可以遵循的一般规则是,不返回IObservable<T>
或Task<T>
的任何Rx方法都将导致订阅(*)
* - 技术上不正确。但是如果你这样想的话,你的大脑会感觉更好。