public void AsyncQueue_Test() { var queue = new AsyncQueue <int>(); var testDataCount = 10000; var tasks = new List <Task>(); var expected = new List <int>(); var producerLock = new SemaphoreSlim(1); var consumerLock = new SemaphoreSlim(1); var random = new Random(); //multi-threaded async producer tasks.AddRange(Enumerable.Range(1, testDataCount).Select(async x => { await Task.Delay(random.Next(0, 1)); await producerLock.WaitAsync(); expected.Add(x); await queue.EnqueueAsync(x); producerLock.Release(); })); var actual = new List <int>(); //multi-threaded async consumer tasks.AddRange(Enumerable.Range(1, testDataCount).Select(async x => { await Task.Delay(random.Next(0, 1)); await consumerLock.WaitAsync(); actual.Add(await queue.DequeueAsync()); consumerLock.Release(); })); Task.WaitAll(tasks.ToArray()); CollectionAssert.AreEqual(expected, actual); }
public async Task AsyncQueueSkipsCancelledTasks() { AsyncQueue <int> inputQueue = new AsyncQueue <int>(); // Queue up a couple of tasks to wait for input CancellationTokenSource cancellationSource = new CancellationTokenSource(); Task <int> taskOne = inputQueue.DequeueAsync(cancellationSource.Token); Task <int> taskTwo = inputQueue.DequeueAsync(); // Cancel the first task and then enqueue a number cancellationSource.Cancel(); await inputQueue.EnqueueAsync(1); // Did the second task get the number? Assert.Equal(TaskStatus.Canceled, taskOne.Status); Assert.Equal(TaskStatus.RanToCompletion, taskTwo.Status); Assert.Equal(1, taskTwo.Result); }
public async Task AsyncQueueSkipsCancelledTasks() { AsyncQueue<int> inputQueue = new AsyncQueue<int>(); // Queue up a couple of tasks to wait for input CancellationTokenSource cancellationSource = new CancellationTokenSource(); Task<int> taskOne = inputQueue.DequeueAsync(cancellationSource.Token); Task<int> taskTwo = inputQueue.DequeueAsync(); // Cancel the first task and then enqueue a number cancellationSource.Cancel(); await inputQueue.EnqueueAsync(1); // Did the second task get the number? Assert.Equal(TaskStatus.Canceled, taskOne.Status); Assert.Equal(TaskStatus.RanToCompletion, taskTwo.Status); Assert.Equal(1, taskTwo.Result); }
public async Task AsyncQueueSynchronizesAccess() { ConcurrentBag <int> outputItems = new ConcurrentBag <int>(); AsyncQueue <int> inputQueue = new AsyncQueue <int>(Enumerable.Range(0, 100)); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); try { // Start 5 consumers await Task.WhenAll( Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run( async() => { // Wait for a bit and then add more items to the queue await Task.Delay(250); foreach (var i in Enumerable.Range(100, 200)) { await inputQueue.EnqueueAsync(i); } // Cancel the waiters cancellationTokenSource.Cancel(); })); } catch (TaskCanceledException) { // Do nothing, this is expected. } // At this point, numbers 0 through 299 should be in the outputItems IEnumerable <int> expectedItems = Enumerable.Range(0, 300); Assert.Equal(0, expectedItems.Except(outputItems).Count()); }
public async Task AsyncQueueSynchronizesAccess() { ConcurrentBag<int> outputItems = new ConcurrentBag<int>(); AsyncQueue<int> inputQueue = new AsyncQueue<int>(Enumerable.Range(0, 100)); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); try { // Start 5 consumers await Task.WhenAll( Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run(() => ConsumeItems(inputQueue, outputItems, cancellationTokenSource.Token)), Task.Run( async () => { // Wait for a bit and then add more items to the queue await Task.Delay(250); foreach (var i in Enumerable.Range(100, 200)) { await inputQueue.EnqueueAsync(i); } // Cancel the waiters cancellationTokenSource.Cancel(); })); } catch (TaskCanceledException) { // Do nothing, this is expected. } // At this point, numbers 0 through 299 should be in the outputItems IEnumerable<int> expectedItems = Enumerable.Range(0, 300); Assert.Equal(0, expectedItems.Except(outputItems).Count()); }