[英]While the OnNext is running, I want to drop all incoming notifications except from the latest
I have some observable, that produces items over time.我有一些可观察的,随着时间的推移会产生项目。 Intervals between items is almost random.
项目之间的间隔几乎是随机的。 I subscribe to my observable and process item, each process can take a lot of time and when
OnNext
ends its work, many new items are produced.我订阅了我的可观察和流程项目,每个流程都可能花费很多时间,当
OnNext
结束其工作时,会产生许多新项目。 I need to take only last item and process it.我只需要拿走最后一项并进行处理。 So every time long
OnNext
operation completes I need do OnNext
for latest item from items that was produced during previous OnNext
run.因此,每次长
OnNext
操作完成时,我都需要对上一次OnNext
运行期间生成的项目中的最新项目执行OnNext
。 Can I do it with Rx?我可以用 Rx 做吗?
I tried Window(1).Switch()
but seems like it executes immediately when item comes, not when OnNext
completed.我尝试了
Window(1).Switch()
但似乎它在项目到来时立即执行,而不是在OnNext
完成时执行。
Here is relatively simple custom DroppingDo
operator, that probably does what you want.这是相对简单的自定义
DroppingDo
运算符,它可能可以满足您的需求。 It is somewhat similar with the built-in Do
operator, with the difference that it invokes the action on the ThreadPool
instead of the current thread, and that it ignores items that are received while a previous action is running.它与内置的
Do
运算符有些相似,不同之处在于它调用ThreadPool
而不是当前线程上的操作,并且它忽略在前一个操作运行时接收到的项目。 The latest item is preserved though.虽然保留了最新的项目。
/// <summary>
/// Invokes an action sequentially for each element in the observable sequence,
/// on the specified scheduler, skipping and dropping elements that are received
/// during the execution of a previous action, except from the latest element.
/// </summary>
public static IObservable<TSource> DroppingDo<TSource>(
this IObservable<TSource> source,
Action<TSource> action,
IScheduler scheduler = null)
{
// Arguments validation omitted
scheduler ??= Scheduler.Default;
return Observable.Defer(() =>
{
Tuple<TSource> latest = null;
return source
.Select(item =>
{
var previous = Interlocked.Exchange(ref latest, Tuple.Create(item));
if (previous != null) return Observable.Empty<TSource>();
return Observable.Defer(() =>
{
var current = Interlocked.Exchange(ref latest, null);
Debug.Assert(current != null);
var unboxed = current.Item1;
return Observable.Start(
() => { action(unboxed); return unboxed; }, scheduler);
});
})
.Concat();
});
}
Usage example.使用示例。 Just replace your code that probably looks like this:
只需替换可能如下所示的代码:
someObservable
.Subscribe(x => Process(x), ex => HandleError(ex));
With this:有了这个:
someObservable
.DroppingDo(x => Process(x))
.Subscribe(_ => { }, ex => HandleError(ex));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.