예제 #1
0
        /// <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 = Time + Scheduler.Normalize(dueTime);

            var si = new ScheduledItem <TimeSpan, TState>(this, state, action, dt);

            var queue = GetQueue();

            if (queue == null)
            {
                queue = new SchedulerQueue <TimeSpan>(4);
                queue.Enqueue(si);

                CurrentThreadScheduler.SetQueue(queue);
                try
                {
                    Trampoline.Run(queue);
                }
                finally
                {
                    CurrentThreadScheduler.SetQueue(null);
                }
            }
            else
            {
                queue.Enqueue(si);
            }

            return(Disposable.Create(si.Cancel));
        }
예제 #2
0
 private static void SetQueue(SchedulerQueue <TimeSpan> newQueue)
 {
     lock (s_queues)
     {
         if (newQueue == null)
         {
             s_queues.Remove(Thread.CurrentThread.ManagedThreadId);
         }
         else
         {
             s_queues[Thread.CurrentThread.ManagedThreadId] = newQueue;
         }
     }
 }
예제 #3
0
        internal EventLoopScheduler(Func <ThreadStart, Thread> threadFactory)
        {
#endif
            _threadFactory = threadFactory ?? throw new ArgumentNullException(nameof(threadFactory));
            _stopwatch     = ConcurrencyAbstractionLayer.Current.StartStopwatch();

            _gate = new object();

            _evt       = new SemaphoreSlim(0);
            _queue     = new SchedulerQueue <TimeSpan>();
            _readyList = new Queue <ScheduledItem <TimeSpan> >();

            ExitIfEmpty = false;
        }
        internal EventLoopScheduler(Func <ThreadStart, Thread> threadFactory)
        {
#endif
            _threadFactory = threadFactory;
            _stopwatch     = ConcurrencyAbstractionLayer.Current.StartStopwatch();

            _gate = new object();

            _evt       = new SemaphoreSlim(0);
            _queue     = new SchedulerQueue <TimeSpan>();
            _readyList = new Queue <ScheduledItem <TimeSpan> >();

            _nextTimer = new SerialDisposable();

            ExitIfEmpty = false;
        }
예제 #5
0
            public static void Run(SchedulerQueue <TimeSpan> queue)
            {
                while (queue.Count > 0)
                {
                    var item = queue.Dequeue();
                    if (!item.IsCanceled)
                    {
                        var wait = item.DueTime - CurrentThreadScheduler.Time;
                        if (wait.Ticks > 0)
                        {
                            ConcurrencyAbstractionLayer.Current.Sleep(wait);
                        }

                        if (!item.IsCanceled)
                        {
                            item.Invoke();
                        }
                    }
                }
            }
예제 #6
0
            public static void Run(SchedulerQueue <TimeSpan> queue)
            {
                while (queue.Count > 0)
                {
                    var item = queue.Dequeue();
                    if (!item.IsCanceled)
                    {
                        var wait = item.DueTime - CurrentThreadScheduler.Time;
                        if (wait.Ticks > 0)
                        {
                            ConcurrencyAbstractionLayer.Current.Sleep(wait);
                        }
// There we can see the Observer.OnNext() is called!!!
                        if (!item.IsCanceled)
                        {
                            item.Invoke();
                        }
                    }
                }
            }
예제 #7
0
 private static void SetQueue(SchedulerQueue <TimeSpan> newQueue)
 {
     s_threadLocalQueue = newQueue;
 }
예제 #8
0
        /// <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 <c>null</c>.</exception>
        public override IDisposable Schedule <TState>(TState state, TimeSpan dueTime, Func <IScheduler, TState, IDisposable> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            var queue = default(SchedulerQueue <TimeSpan>);

            // There is no timed task and no task is currently running
            if (!running)
            {
                running = true;

                if (dueTime > TimeSpan.Zero)
                {
                    ConcurrencyAbstractionLayer.Current.Sleep(dueTime);
                }

                // execute directly without queueing
                IDisposable d;
                try
                {
                    d = action(this, state);
                }
                catch
                {
                    SetQueue(null);
                    running = false;
                    throw;
                }

                // did recursive tasks arrive?
                queue = GetQueue();

                // yes, run those in the queue as well
                if (queue != null)
                {
                    try
                    {
                        Trampoline.Run(queue);
                    }
                    finally
                    {
                        SetQueue(null);
                        running = false;
                    }
                }
                else
                {
                    running = false;
                }

                return(d);
            }

            queue = GetQueue();

            // if there is a task running or there is a queue
            if (queue == null)
            {
                queue = new SchedulerQueue <TimeSpan>(4);
                SetQueue(queue);
            }

            var dt = Time + Scheduler.Normalize(dueTime);

            // queue up more work
            var si = new ScheduledItem <TimeSpan, TState>(this, state, action, dt);

            queue.Enqueue(si);
            return(si);
        }