给定来自事件流的IObservable序列:
IObservable<MyEvent> observable = EventAggregator.GetEvent<MyEvent>()
我第一次出现事件:
MyEvent myEvent = await observable.FirstOrDefaultAsync();
然而,我想要处理订阅,resp。当用户点击取消按钮时,中断observable。
目前我使用.ToTask()扩展方法的解决方法,但我相信只有基于Rective扩展的更清晰的解决方案。
_tsc = new CancellationTokenSource();
MyEvent myEvent;
try
{
myEvent = await EventAggregator.GetEvent<MyEvent>()
.FirstOrDefaultAsync()
.ToTask(__tsc.Token);
}
catch (TaskCanceledException)
{
myEvent = null;
}
void Cancel()
{
_tsc.Cancel();
}
答案 0 :(得分:1)
我不确定这是&#34;更干净&#34;,但你可以在没有ToTask
的情况下做到这一点:
static async void Test(IObservable<int> ob, CancellationToken ct)
{
var first = await ob.TakeUntil(Observable.Create<Unit>(o => ct.Register(() => {
o.OnNext(Unit.Default);
o.OnCompleted();
}))).FirstOrDefaultAsync();
}
因此我们创建另一个observable,当取消令牌被取消时将生成一个元素,然后我们使用TakeUntil
重载,它将从第一个序列返回元素,直到第二个序列生成一个元素。因此,在您取消令牌后 - 您的await
语句将返回默认值(null
作为参考类型)。
您可以将其移至扩展方法,然后它会更好看:
public static class Extensions {
public static IObservable<T> TakeUntilCancelled<T>(this IObservable<T> ob, CancellationToken ct) {
return ob.TakeUntil(Observable.Create<Unit>(o => ct.Register(() =>
{
o.OnNext(Unit.Default);
o.OnCompleted();
})));
}
}
var first = await ob.TakeUntilCancelled(ct).FirstOrDefaultAsync();
答案 1 :(得分:0)
使用内置的Rx操作符,您想要做的事情非常简单。
这样做:
IObservable<MyEvent> observable = EventAggregator.GetEvent<MyEvent>()
var endItAll = new Subject<Unit>();
MyEvent myEvent = await observable.TakeUntil(endItAll).FirstOrDefaultAsync();
现在,您只需致电endItAll.OnNext(Unit.Default)
即可结束订阅并返回null
MyEvent
。