public void ConcurrentEnqueAndDequeueMultiWriters() { // One reader assert all values should be received. Prop.ForAll <int[]>(expectedList => { Array.Sort(expectedList); var queue = new ConcurrentAsyncQueue <int>(); int numWriters = 4; var cancelSource = new CancellationTokenSource(); CancellationToken cancelToken = cancelSource.Token; long remainingToRead = expectedList.Length; int startValue = 0; if (expectedList.Length > 0) { startValue = expectedList[0]; } var allTasks = new List <Task>(); // can't move to separate fn because of `ref` var reader1 = ReaderTask(startValue, cancelToken, queue, (a, b) => { Interlocked.Decrement(ref remainingToRead); }); allTasks.Add(reader1); for (int i = 0; i < numWriters; ++i) { int myIndex = i; allTasks.Add(Task.Run(() => { for (int j = myIndex; j < expectedList.Length; j += numWriters) { queue.Enqueue(expectedList[j]); } })); } allTasks.Add(Task.Run(async() => { while (Interlocked.Read(ref remainingToRead) > 0) { await Task.Delay(10); } cancelSource.Cancel(); })); Task.WaitAll(allTasks.ToArray()); var actualList = reader1.Result; AssertIfNotEqual(expectedList, actualList); }).Check(testConfig); }
static Task WriterTask <T>(T[] list, ConcurrentAsyncQueue <T> queue) { return(Task.Run(() => { foreach (var x in list) { queue.Enqueue(x); } })); }
async public Task <long> ConcurrentAsyncQueueEnqueueDequeue() { using (var asyncQueue = new ConcurrentAsyncQueue <int>()) { long sum = 0; for (int i = 0; i < N; ++i) { asyncQueue.Enqueue(i); sum += await asyncQueue.DequeueAsync(); } return(sum); } }
public void ConcurrentEnqueAndDequeueHappensInOrder() { Prop.ForAll <int[]>(xs => { var queue = new ConcurrentAsyncQueue <int>(); var writerTask = WriterTask(xs, queue); bool allSuccess = true; Task readerTask = Task.Run(async() => { foreach (var expected in xs) { var actual = await queue.DequeueAsync(); Assert.AreEqual(expected, actual); allSuccess = allSuccess && (expected == actual); } }); Task.WaitAll(writerTask, readerTask); return(allSuccess); }).Check(testConfig); }
public void ConcurrentEnqueAndDequeueMultiReaders() { // Multiple Readers assert that they receive values in increasing order. // All values should be received. Prop.ForAll <int[]>(expectedList => { Array.Sort(expectedList); var queue = new ConcurrentAsyncQueue <int>(); var cancelSource = new CancellationTokenSource(); CancellationToken cancelToken = cancelSource.Token; long remainingToRead = expectedList.Length; int startValue = 0; if (expectedList.Length > 0) { startValue = expectedList[0]; } var allTasks = new List <Task>(); // can't move to separate fn because of `ref` var reader1 = ReaderTask(startValue, cancelToken, queue, (a, b) => { Interlocked.Decrement(ref remainingToRead); Assert.IsTrue(a >= b); }); allTasks.Add(reader1); var reader2 = ReaderTask(startValue, cancelToken, queue, (a, b) => { Interlocked.Decrement(ref remainingToRead); Assert.IsTrue(a >= b); }); allTasks.Add(reader2); // writer task allTasks.Add(WriterTask(expectedList, queue)); var reader3 = ReaderTask(startValue, cancelToken, queue, (a, b) => { Interlocked.Decrement(ref remainingToRead); Assert.IsTrue(a >= b); }); allTasks.Add(reader3); var reader4 = ReaderTask(startValue, cancelToken, queue, (a, b) => { Interlocked.Decrement(ref remainingToRead); Assert.IsTrue(a >= b); }); allTasks.Add(reader4); // Stop Task allTasks.Add(Task.Run(async() => { while (Interlocked.Read(ref remainingToRead) > 0) { await Task.Delay(10); } cancelSource.Cancel(); })); Task.WaitAll(allTasks.ToArray()); var actualList = MergeSortList(new List <int>[] { reader1.Result, reader2.Result, reader3.Result, reader4.Result }); AssertIfNotEqual(expectedList, actualList); }).Check(testConfig); }
static async Task <List <T> > ReaderTask <T>(T startValueRead, CancellationToken cancelToken, ConcurrentAsyncQueue <T> queue, Action <T, T> afterReadValue) { T lastValueRead = startValueRead; var list = new List <T>(); while (!cancelToken.IsCancellationRequested) { T curValue = lastValueRead; try { curValue = await queue.DequeueAsync(cancelToken); } catch (OperationCanceledException) { break; } list.Add(curValue); afterReadValue(curValue, lastValueRead); lastValueRead = curValue; } return(list); }