public void SmartProcessingQueueEnqueuesOperationIfProcessQueueIsFullAndCurrentlyRunningTaskFails()
        {
            bool operation1Processed = false;
            bool operation2Processed = false;

            var queue = new SmartThrottledProcessingQueue(1);
            ManualResetEventSlim pause = new ManualResetEventSlim(false);

            Task operation1 = new Task(() =>
            {
                //simulate a long running operation
                Thread.Sleep(TimeSpan.FromMilliseconds(100));
                operation1Processed = true;
                // throw exception to simulate failed operation
                throw new InvalidOperationException();
            });
            Task operation2 = new Task(() =>
            {
                operation2Processed = true;
                pause.Set();
            });

            queue.RegisterOperation(operation1);
            queue.RegisterOperation(operation2);

            pause.Wait(TimeSpan.FromSeconds(10));

            Assert.IsTrue(operation1Processed);
            Assert.IsTrue(operation2Processed);
        }
        public void SmartProcessingQueueOperationsInProcessDoesNotExceedMaxOperationsMultiThreaded()
        {
            const int expected = 20;

            bool maxOperationsExceeded = false;
            int  operationsProcessed   = 0;

            ManualResetEventSlim pause = new ManualResetEventSlim(false);

            var    queue  = new SmartThrottledProcessingQueue(10);
            Random random = new Random();

            Parallel.For(0, 20, i => queue.RegisterOperation(new Task(() =>
            {
                if (queue.OperationsInProcess == 20)
                {
                    maxOperationsExceeded = true;
                }

                //simulate operation running
                Thread.Sleep(TimeSpan.FromMilliseconds(random.Next(0, 200)));

                Interlocked.Increment(ref operationsProcessed);
                if (operationsProcessed == 20)
                {
                    pause.Set();
                }
            })));

            pause.Wait(TimeSpan.FromSeconds(10));

            Assert.IsFalse(maxOperationsExceeded);
            Assert.AreEqual(expected, operationsProcessed);
        }
        public void SmartProcessingQueueEnqueuesOperationsIfProcessQueueIsFullMultiThreaded()
        {
            bool operation1Processed = false;
            bool operation2Processed = false;

            var queue = new SmartThrottledProcessingQueue(10);
            ManualResetEventSlim pause = new ManualResetEventSlim(false);

            Parallel.For(0, 10, i => queue.RegisterOperation(new Task(() =>
            {
                //simulate long running operation
                Thread.Sleep(TimeSpan.FromMilliseconds(100));
                operation1Processed = true;
            })));
            queue.RegisterOperation(new Task(() =>
            {
                operation2Processed = true;
                pause.Set();
            }));

            pause.Wait(TimeSpan.FromSeconds(10));

            Assert.IsTrue(operation1Processed);
            Assert.IsTrue(operation2Processed);
        }
        public void SmartProcessingQueueEnqueueOperationThrowsIfTaskSchedulerIsNull()
        {
            var queue = new SmartThrottledProcessingQueue();

            Task t = new Task(() => { });

            Assert.Throws <ArgumentNullException>(() => queue.RegisterOperation(t, null as TaskScheduler));
        }
        public void SmartProcessingQueueEnqueueOperationThrowsIfTaskIsAlreadyStarted()
        {
            var queue = new SmartThrottledProcessingQueue();

            Task t = Task.Factory.StartNew(() => { });

            Assert.Throws <ArgumentException>(() => queue.RegisterOperation(t));
        }
        public void SmartProcessingQueueEnqueueOperationThrowsIfTaskCollectionContainsNull()
        {
            var queue = new SmartThrottledProcessingQueue();

            Task[] tasks = new[] { new Task(() => { }), null, new Task(() => { }) };

            Assert.Throws <ArgumentException>(() => queue.RegisterOperations(tasks));
        }
        /// <summary>
        /// Registers a collection of operations for processing against a specified <see cref="TaskScheduler"/>.
        /// </summary>
        /// <param name="queue">The queue to register the operations against.</param>
        /// <param name="operations">A collection of tasks representing the operations.</param>
        /// <param name="scheduler">A scheduler.</param>
        /// <exception cref="ArgumentNullException"><paramref name="operations"/> was null or contained a null entry.</exception>
        /// <exception cref="ArgumentException"><paramref name="operations"/> contained a task that has already been started or completed.</exception>
        public static void RegisterOperations(this SmartThrottledProcessingQueue queue, IEnumerable <Task> operations, TaskScheduler scheduler)
        {
            queue.ThrowIfNull(nameof(queue), $"{nameof(queue)} parameter cannot be null");
            operations.ThrowIfNullOrContainsNull(nameof(operations), $"{nameof(operations)} parameter cannot be null");

            foreach (var operation in operations)
            {
                queue.RegisterOperation(operation, scheduler);
            }
        }
        public void SmartProcessingQueueStartsOperationIfProcessQueueIsNotFull()
        {
            bool operationProcessed = false;

            var queue = new SmartThrottledProcessingQueue();

            Task operation = new Task(() =>
            {
                operationProcessed = true;
            });

            queue.RegisterOperations(new[] { operation });

            operation.Wait();

            Assert.IsTrue(operationProcessed);
        }
        public void SmartProcessingQueueEnqueueOperationThrowsIfTasksCollectionIsNull()
        {
            var queue = new SmartThrottledProcessingQueue();

            Assert.Throws <ArgumentNullException>(() => queue.RegisterOperations(null as Task[]));
        }
        public void SmartProcessingQueueInitialisesWithSpecifiedMaxOperations()
        {
            var queue = new SmartThrottledProcessingQueue(100);

            Assert.IsNotNull(queue);
        }
        public void SmartProcessingQueueInitialises()
        {
            var queue = new SmartThrottledProcessingQueue();

            Assert.IsNotNull(queue);
        }
 /// <summary>
 /// Registers a collection of operations for processing against the current <see cref="TaskScheduler"/>.
 /// </summary>
 /// <param name="queue">The queue to register the operations against.</param>
 /// <param name="operations">A collection of tasks representing the operations.</param>
 /// <exception cref="ArgumentNullException"><paramref name="operations"/> was null or contained a null entry.</exception>
 /// <exception cref="ArgumentException"><paramref name="operations"/> contained a task that has already been started or completed.</exception>
 public static void RegisterOperations(this SmartThrottledProcessingQueue queue, IEnumerable <Task> operations)
 {
     RegisterOperations(queue, operations, TaskScheduler.Current);
 }