Esempio n. 1
0
        public void MultipleAssignment()
        {
            var d = new MultipleAssignmentDisposable();
            d.IsDisposed.IsFalse();
            var id1 = new IdDisp(1);
            var id2 = new IdDisp(2);
            var id3 = new IdDisp(3);

            // dispose first
            d.Dispose();
            d.IsDisposed.IsTrue();

            d.Disposable = id1; id1.IsDisposed.IsTrue();
            d.Disposable = id2; id2.IsDisposed.IsTrue();
            d.Disposable = id3; id3.IsDisposed.IsTrue();

            // normal flow
            d = new MultipleAssignmentDisposable();
            id1 = new IdDisp(1);
            id2 = new IdDisp(2);
            id3 = new IdDisp(3);

            d.Disposable = id1; id1.IsDisposed.IsFalse();
            d.Dispose();
            id1.IsDisposed.IsTrue();
            d.Disposable = id2; id2.IsDisposed.IsTrue();
            d.Disposable = id3; id3.IsDisposed.IsTrue();

            // exception flow
            d = new MultipleAssignmentDisposable();
            id1 = new IdDisp(1);
            id2 = new IdDisp(2);
            id3 = new IdDisp(3);
            d.Disposable = id1;
            d.Disposable = id2;
            d.Disposable = id3;
            d.Dispose();
            id1.IsDisposed.IsFalse();
            id2.IsDisposed.IsFalse();
            id3.IsDisposed.IsTrue();

            // null
            d = new MultipleAssignmentDisposable();
            id1 = new IdDisp(1);
            d.Disposable = null;
            d.Dispose();
            d.Disposable = null;
        }
Esempio n. 2
0
        private IDisposable ScheduleSlow <TState>(TState state, TimeSpan dueTime, Func <IScheduler, TState, IDisposable> action)
        {
            var d = new MultipleAssignmentDisposable();

            var timer = new System.Windows.Threading.DispatcherTimer(Priority, Dispatcher);

            timer.Tick += (s, e) =>
            {
                var t = Interlocked.Exchange(ref timer, null);
                if (t != null)
                {
                    try
                    {
                        d.Disposable = action(this, state);
                    }
                    finally
                    {
                        t.Stop();
                        action = null;
                    }
                }
            };

            timer.Interval = dueTime;
            timer.Start();

            d.Disposable = Disposable.Create(() =>
            {
                var t = Interlocked.Exchange(ref timer, null);
                if (t != null)
                {
                    t.Stop();
                    action = (_, __) => Disposable.Empty;
                }
            });

            return(d);
        }
Esempio n. 3
0
    /// <summary>
    /// Schedules an action to be executed after dueTime on the message loop associated with the control, using a Windows Forms Timer object.
    /// </summary>
    /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
    /// <param name="state">State passed to the action to be executed.</param>
    /// <param name="action">Action to be executed.</param>
    /// <param name="dueTime">Relative time after which to execute the action.</param>
    /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
    /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
    public override IDisposable Schedule <TState>(TState state, TimeSpan dueTime, Func <IScheduler, TState, IDisposable> action)
    {
        if (action == null)
        {
            throw new ArgumentNullException(nameof(action));
        }

        var dt = Scheduler.Normalize(dueTime);

        if (dt.Ticks == 0)
        {
            return(Schedule(state, action));
        }

        var createTimer = new Func <IScheduler, TState, IDisposable>((scheduler1, state1) =>
        {
            var d = new MultipleAssignmentDisposable();

            var timer = new System.Windows.Forms.Timer();

            timer.Tick += (s, e) =>
            {
                var t = Interlocked.Exchange(ref timer, null);
                if (t != null)
                {
                    try
                    {
                        if (!_control.IsDisposed && !d.IsDisposed)
                        {
                            d.Disposable = action(scheduler1, state1);
                        }
                    }
                    finally
                    {
                        t.Stop();
                        action = static (s, t) => Disposable.Empty;
                    }
                }
Esempio n. 4
0
        public static IObservable <T> ObserveLatestOn <T>(this IObservable <T> source, IScheduler scheduler)
        => Observable.Create <T>(observer => {
            Notification <T> outsideNotification;
            var gate       = new object();
            var active     = false;
            var cancelable = new MultipleAssignmentDisposable();
            var disposable = source.Materialize().Subscribe(thisNotification => {
                bool wasNotAlreadyActive;
                lock (gate){
                    wasNotAlreadyActive = !active;
                    active = true;
                    outsideNotification = thisNotification;
                }

                if (wasNotAlreadyActive)
                {
                    cancelable.Disposable = scheduler.Schedule(self => {
                        Notification <T> localNotification;
                        lock (gate){
                            localNotification   = outsideNotification;
                            outsideNotification = null;
                        }

                        localNotification.Accept(observer);
                        bool hasPendingNotification;
                        lock (gate){
                            hasPendingNotification = active = outsideNotification != null;
                        }

                        if (hasPendingNotification)
                        {
                            self();
                        }
                    });
                }
            });
            return(new CompositeDisposable(disposable, cancelable));
        });
        /// <summary>
        /// Schedules an action to be executed after dueTime.
        /// </summary>
        /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
        /// <param name="state">State passed to the action to be executed.</param>
        /// <param name="action">Action to be executed.</param>
        /// <param name="dueTime">Relative time after which to execute the action.</param>
        /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
        /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
        public override IDisposable Schedule <TState>(TState state, TimeSpan dueTime, Func <IScheduler, TState, IDisposable> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            var dt = Scheduler.Normalize(dueTime);

            if (dt.Ticks == 0)
            {
                return(Schedule(state, action));
            }

#if !NO_TASK_DELAY
            var d = new MultipleAssignmentDisposable();

            var ct = new CancellationDisposable();
            d.Disposable = ct;

#if USE_TASKEX
            TaskEx.Delay(dueTime, ct.Token).ContinueWith(_ =>
#else
            Task.Delay(dueTime, ct.Token).ContinueWith(_ =>
#endif
            {
                if (!d.IsDisposed)
                {
                    d.Disposable = action(this, state);
                }
            }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, taskFactory.Scheduler);

            return(d);
#else
            return(DefaultScheduler.Instance.Schedule(state, dt, (_, state1) => Schedule(state1, action)));
#endif
        }
Esempio n. 6
0
        protected override IDisposable SubscribeCore(IObserver <T> observer, IDisposable cancel)
        {
            if (dueTimeT != null)
            {
                var d  = new MultipleAssignmentDisposable();
                var dt = Scheduler.Normalize(dueTimeT.Value);

                d.Disposable = scheduler.Schedule(dt, () => {
                    d.Disposable = source.Subscribe(observer);
                });

                return(d);
            }
            else
            {
                var d = new MultipleAssignmentDisposable();

                d.Disposable = scheduler.Schedule(dueTimeD.Value, () => {
                    d.Disposable = source.Subscribe(observer);
                });

                return(d);
            }
        }
Esempio n. 7
0
                public IDisposable Schedule(Action action, TimeSpan delay)
                {
                    MultipleAssignmentDisposable inner = new MultipleAssignmentDisposable();

                    MultipleAssignmentDisposable outer = new MultipleAssignmentDisposable(inner);

                    if (tasks.Add(outer))
                    {
                        IDisposable cancel = new ActionWeakDisposable(() => tasks.Remove(outer));

                        IDisposable f = Task.Delay(delay).ContinueWith(a =>
                        {
                            if (!outer.IsDisposed())
                            {
                                outer.Set(Schedule(action));
                            }
                        });

                        inner.Set(f);

                        return(cancel);
                    }
                    return(EmptyDisposable.Instance);
                }
 public static Func <Action <TResult>, Action <Exception>, IBackgroundTask> CreateForAsync <TResult>(FSharpAsync <TResult> async)
 {
     return((onSuccess, onError) => {
         var disp = new MultipleAssignmentDisposable();
         var backgroundTask = new AnonymousBackgroundTask();
         backgroundTask.name = "upgarde firmware";
         backgroundTask.state = BackgroundTaskState.InProgress;
         backgroundTask.disposable = Disposable.Create(() => {
             disp.Dispose();
             backgroundTask.state = BackgroundTaskState.Canceled;
         });
         disp.Disposable = async.Subscribe(
             res => {
             onSuccess(res);
             backgroundTask.state = BackgroundTaskState.Completed;
         },
             err => {
             onError(err);
             backgroundTask.state = BackgroundTaskState.Failed;
         }
             );
         return backgroundTask;
     });
 }
            public override IDisposable Schedule(IRunnable action, TimeSpan delay)
            {
                MultipleAssignmentDisposable first = new MultipleAssignmentDisposable();
                MultipleAssignmentDisposable mad = new MultipleAssignmentDisposable(first);

                IDisposable d = Task.Delay(delay).ContinueWith(t => {
                    IDisposable d1 = Schedule(action);
                    mad.Set(d1);
                });

                first.Set(d);

                return mad;
            }
Esempio n. 10
0
        /// <summary>
        /// Schedules an action to be executed after dueTime on the message loop associated with the control, using a Windows Forms Timer object.
        /// </summary>
        /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam>
        /// <param name="state">State passed to the action to be executed.</param>
        /// <param name="action">Action to be executed.</param>
        /// <param name="dueTime">Relative time after which to execute the action.</param>
        /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>
        /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
        public override IDisposable Schedule <TState>(TState state, TimeSpan dueTime, Func <IScheduler, TState, IDisposable> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            var dt = Scheduler.Normalize(dueTime);

            if (dt.Ticks == 0)
            {
                return(Schedule(state, action));
            }

            var createTimer = new Func <IScheduler, TState, IDisposable>((scheduler1, state1) =>
            {
                var d = new MultipleAssignmentDisposable();

                var timer = new System.Windows.Forms.Timer();

                timer.Tick += (s, e) =>
                {
                    var t = Interlocked.Exchange(ref timer, null);
                    if (t != null)
                    {
                        try
                        {
                            d.Disposable = action(scheduler1, state1);
                        }
                        finally
                        {
                            t.Stop();
                            action = null;
                        }
                    }
                };

                timer.Interval = (int)dt.TotalMilliseconds;
                timer.Start();

                d.Disposable = Disposable.Create(() =>
                {
                    var t = Interlocked.Exchange(ref timer, null);
                    if (t != null)
                    {
                        t.Stop();
                        action = (_, __) => Disposable.Empty;
                    }
                });

                return(d);
            });

            //
            // This check is critical. When creating and enabling a Timer object on another thread than
            // the UI thread, it won't fire.
            //
            if (_control.InvokeRequired)
            {
                return(Schedule(state, createTimer));
            }
            else
            {
                return(createTimer(this, state));
            }
        }
        /// <summary>
        /// Applies a conflation algorithm to an observable stream.
        /// Anytime the stream OnNext twice below minimumUpdatePeriod, the second update gets delayed to respect the minimumUpdatePeriod
        /// If more than 2 update happen, only the last update is pushed
        /// Updates are pushed and rescheduled using the provided scheduler
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">stream</param>
        /// <param name="minimumUpdatePeriod">minimum delay between 2 updates</param>
        /// <param name="scheduler">to be used to publish updates and schedule delayed updates</param>
        /// <returns></returns>
        public static IObservable <T> Conflate <T>(this IObservable <T> source, TimeSpan minimumUpdatePeriod, IScheduler scheduler)
        {
            return(Observable.Create <T>(observer =>
            {
                // indicate when the last update was published
                var lastUpdateTime = DateTimeOffset.MinValue;
                // indicate if an update is currently scheduled
                var updateScheduled = new MultipleAssignmentDisposable();
                // indicate if completion has been requested (we can't complete immediatly if an update is in flight)
                var completionRequested = false;
                var gate = new object();

                var subscription = source
                                   .ObserveOn(scheduler)
                                   .Subscribe(
                    x =>
                {
                    var currentUpdateTime = scheduler.Now;

                    bool scheduleRequired;
                    lock (gate)
                    {
                        scheduleRequired = currentUpdateTime - lastUpdateTime < minimumUpdatePeriod;
                        if (scheduleRequired && updateScheduled.Disposable != null)
                        {
                            updateScheduled.Disposable.Dispose();
                            updateScheduled.Disposable = null;
                        }
                    }

                    if (scheduleRequired)
                    {
                        updateScheduled.Disposable = scheduler.Schedule(lastUpdateTime + minimumUpdatePeriod, () =>
                        {
                            observer.OnNext(x);

                            lock (gate)
                            {
                                lastUpdateTime = scheduler.Now;
                                updateScheduled.Disposable = null;
                                if (completionRequested)
                                {
                                    observer.OnCompleted();
                                }
                            }
                        });
                    }
                    else
                    {
                        observer.OnNext(x);
                        lock (gate)
                        {
                            lastUpdateTime = scheduler.Now;
                        }
                    }
                },
                    observer.OnError,
                    () =>
                {
                    // if we have scheduled an update we need to complete once the update has been published
                    if (updateScheduled.Disposable != null)
                    {
                        lock (gate)
                        {
                            completionRequested = true;
                        }
                    }
                    else
                    {
                        observer.OnCompleted();
                    }
                });

                return subscription;
            }));
        }
        public IDisposable Subscribe(
            Endpoint endpoint,
            Action <BinaryMessage, AcknowledgeDelegate> callback,
            string messageType,
            string processingGroup,
            int priority)
        {
            if (string.IsNullOrEmpty(processingGroup))
            {
                throw new ArgumentNullException(nameof(processingGroup), "should be not empty string");
            }
            if (m_IsDisposing)
            {
                throw new ObjectDisposedException(GetType().Name);
            }

            var          subscriptionHandler = new MultipleAssignmentDisposable();
            Action <int> doSubscribe         = null;

            doSubscribe = attemptNumber =>
            {
                string processingGroupName = null;
                if (subscriptionHandler.IsDisposed)
                {
                    return;
                }

                try
                {
                    var group = GetProcessingGroup(processingGroup);
                    processingGroupName = group.Name;
                    _log.WriteInfo(
                        nameof(ProcessingGroupManager),
                        nameof(Subscribe),
                        attemptNumber > 0
                            ? $"Resubscribing for endpoint {endpoint} within processing group '{processingGroupName}'. Attempt# {attemptNumber}"
                            : $"Subscribing for endpoint {endpoint} within processing group '{processingGroupName}'");

                    var sessionName = GetSessionName(group, priority);

                    var session = m_TransportManager.GetMessagingSession(endpoint, sessionName, Helper.CallOnlyOnce(() =>
                    {
                        _log.WriteInfo(
                            nameof(ProcessingGroupManager),
                            nameof(Subscribe),
                            $"Subscription for endpoint {endpoint} within processing group '{processingGroupName}' failure detected. Attempting subscribe again.");
                        doSubscribe(0);
                    }));

                    var subscription = group.Subscribe(
                        session,
                        endpoint.Destination.Subscribe,
                        (message, ack) => callback(message, CreateDeferredAcknowledge(ack)),
                        messageType,
                        priority);
                    var brokenSubscription = subscriptionHandler.Disposable;
                    subscriptionHandler.Disposable = subscription;
                    try
                    {
                        if (attemptNumber > 0)
                        {
                            brokenSubscription.Dispose();
                        }
                    }
                    catch
                    {
                    }
                    _log.WriteInfo(
                        nameof(ProcessingGroupManager),
                        nameof(Subscribe),
                        $"Subscribed for endpoint {endpoint} in processingGroup '{processingGroupName}' using session {sessionName}");
                }
                catch (InvalidSubscriptionException e)
                {
                    _log.WriteErrorAsync(
                        nameof(ProcessingGroupManager),
                        nameof(Subscribe),
                        $"Failed to subscribe for endpoint {endpoint} within processing group '{processingGroupName}'",
                        e);
                    throw;
                }
                catch (Exception e)
                {
                    _log.WriteErrorAsync(
                        nameof(ProcessingGroupManager),
                        nameof(Subscribe),
                        $"Failed to subscribe for endpoint {endpoint} within processing group '{processingGroupName}'. Attempt# {attemptNumber}. Will retry in {ResubscriptionTimeout}ms",
                        e);
                    ScheduleSubscription(doSubscribe, attemptNumber + 1);
                }
            };
            doSubscribe(0);
            return(subscriptionHandler);
        }
Esempio n. 13
0
 public SubscribeOnCompletableSubscriber(ICompletableSubscriber actual, MultipleAssignmentDisposable mad)
 {
     this.actual = actual;
     this.mad    = mad;
 }