static async Task <int> PushConcurrentlyTwoThousandItemsInPackagesOfFiveHundredIntoFourSlots(MultiProducerConcurrentCompletion <int> completion) { var t1 = Task.Run(() => Parallel.For(1, 500, i => { completion.Push(slotNumber: 0, item: i); })); var t2 = Task.Run(() => Parallel.For(500, 1000, i => { completion.Push(slotNumber: 1, item: i); })); var t3 = Task.Run(() => Parallel.For(1000, 1500, i => { completion.Push(slotNumber: 2, item: i); })); await Task.WhenAll(t1, t2, t3); var numberOfItems = 2000; for (var i = 1500; i < numberOfItems + 1; i++) { completion.Push(slotNumber: 3, item: i); } return(numberOfItems); }
public async Task Pushing_and_complete_with_no_drain_without_start_empties_slots() { var pushedItems = new ConcurrentQueue <List <int> >[4] { new ConcurrentQueue <List <int> >(), new ConcurrentQueue <List <int> >(), new ConcurrentQueue <List <int> >(), new ConcurrentQueue <List <int> >(), }; // choose insanely high batchSize to force push interval picking up all the content var completion = new MultiProducerConcurrentCompletion <int>(batchSize: 100, pushInterval: TimeSpan.FromMilliseconds(1), maxConcurrency: 4, numberOfSlots: 4); await PushConcurrentlyTwoThousandItemsInPackagesOfFiveHundredIntoFourSlots(completion); await completion.Complete(drain : false); var countDownEvent = new CountdownEvent(1); completion.Start((items, slot, state, token) => { pushedItems[slot].Enqueue(new List <int>(items)); // take a copy countDownEvent.Signal(); return(Task.FromResult(0)); }); completion.Push(1, slotNumber: 1); await Task.Run(() => countDownEvent.Wait(TimeSpan.FromSeconds(5))); await completion.Complete(); Assert.AreEqual(1, Flatten(pushedItems).Sum(i => i)); }