/// <summary> /// This method enqueues an action to be run at a later time, according /// to the scheduling policies (i.e. via priority and key). /// </summary> /// <typeparam name="T">The type of item for the observable.</typeparam> /// <typeparam name="TDontCare">Used to allow any observable type.</typeparam> /// <param name="priority">The priority of operation. Higher priorities run before lower ones.</param> /// <param name="key">A key to apply to the operation. Items with the same key will be run in order.</param> /// <param name="cancel">A observable which if signalled, the operation will be cancelled.</param> /// <param name="asyncCalculationFunc">The async method to execute when scheduled.</param> /// <returns>The result of the async calculation.</returns> public IObservable <T> EnqueueObservableOperation <T, TDontCare>(int priority, string key, IObservable <TDontCare> cancel, Func <IObservable <T> > asyncCalculationFunc) { var id = Interlocked.Increment(ref sequenceNumber); var cancelReplay = new ReplaySubject <TDontCare>(); var item = new KeyedOperation <T> { Key = key ?? DefaultKey, Id = id, Priority = priority, CancelSignal = cancelReplay.Select(_ => Unit.Default), Func = asyncCalculationFunc, }; cancel .Do(_ => { Debug.WriteLine("Cancelling {0}", id); item.CancelledEarly = true; }) .Multicast(cancelReplay).Connect(); lock (_queuedOps) { Debug.WriteLine("Queued item {0}, priority {1}", item.Id, item.Priority); _queuedOps.OnNext(item); } return(item.Result); }
private static IObservable <KeyedOperation> ProcessOperation(KeyedOperation operation) { Debug.WriteLine("Processing item {0}, priority {1}", operation.Id, operation.Priority); return(Observable.Defer(operation.EvaluateFunc) .Select(_ => operation) .Catch(Observable.Return(operation))); }