在RX中是否有办法使用repeat观察形式异步,并且只有在所有订阅完成后才调用下一条消息? 例如:
var messages = new Stack<int>(new int[] { 1, 2, 3, 4, 5, 6 });
var observable = Observable
.FromAsync(() => Task.Run(() => messages.Peek()))
.Repeat(6);
observable.Subscribe(async message =>
{
await Task.Delay(2);
Console.WriteLine(message);
messages.Pop();
});
当前输出:666555
所需的输出:654321
完成所有处理后删除邮件的原因是为了确保处理所有邮件。
我知道通过使订阅同步可以实现所需的输出,异步方法可以实现相同的效果吗?
答案 0 :(得分:2)
所以我会这样做(如果我坚持使用Task.Run
):
var messages = new Stack<int>(new int[] { 1, 2, 3, 4, 5, 6 });
var observable =
Observable.While<int>(
() => messages.Count > 0,
Observable.Defer(() =>
Observable.FromAsync(() =>
Task.Run(() => messages.Pop()))));
observable
.Subscribe(async message =>
{
await Task.Delay(2);
Console.WriteLine(message);
});
这会产生如下运行:
3 2 6 5 1 4
每当您看到Observable.FromAsync(() => Task.Run(() => /* something */))
时,您几乎总是将其替换为Observable.Start(() => /* something */)
。如果你不需要,可以在一个observable中调用任务。
代码是:
var observable =
Observable.While<int>(
() => messages.Count > 0,
Observable.Defer(() =>
Observable.Start(() => messages.Pop())));
如果你想要在值之间有一个延迟而你想要它们,那么试试这个:
var observable =
Observable.While<int>(
() => messages.Count > 0,
Observable.Defer(() =>
Observable
.Start(() => messages.Pop())
.Delay(TimeSpan.FromSeconds(2.0))));
observable
.Subscribe(message => Console.WriteLine(message));
或者,有一个选项可能对您更好。试试这个:
var observable =
Observable
.Generate(
0,
n => messages.Count > 0,
n => n + 1,
n => messages.Pop(),
n => TimeSpan.FromSeconds(2.0));
observable
.Subscribe(message => Console.WriteLine(message));
.Generate
运算符非常强大。
如果您希望立即生成第一个值,可以像这样更改:
var observable =
Observable
.Generate(
0,
n => messages.Count > 0,
n => n + 1,
n => messages.Pop(),
n => TimeSpan.FromSeconds(n == 0 ? 0.0 : 2.0));