private static void ExceptionOnMoveNext(int length, int indexToThrow, bool isOrderable) { List <int> ds = new List <int>(); for (int i = 0; i < length; i++) { ds.Add(i); } Exception userEx = new InvalidOperationException("UserException"); //this is an enumerable that will execute user actions on move next, current and dispose //in this case we will set it to throw on MoveNext for specified index UserActionEnumerable <int> customEnumerable = new UserActionEnumerable <int>(ds); Action <int> moveNextUserAction = (currentElement) => { if (currentElement == indexToThrow) { throw userEx; } ; }; customEnumerable.MoveNextAction = moveNextUserAction; var partitioner = Partitioner.Create <int>(customEnumerable, EnumerablePartitionerOptions.NoBuffering); var exception = Assert.Throws <AggregateException>(() => Parallel.ForEach(partitioner, (index) => { })); VerifyAggregateException(exception, userEx); Assert.True(customEnumerable.AreEnumeratorsDisposed()); }
private static void OneMoveNext(int length, bool isOrderable) { Debug.WriteLine("Length: {0} IsOrderable: {1}", length, isOrderable); List <int> ds = new List <int>(); for (int i = 0; i < length; i++) { ds.Add(i); } int dataSourceMoveNextCalls = 0; //this is an enumerable that will execute user actions on move next, current and dispose //in this case we will set it to wait on MoveNext for the even indexes UserActionEnumerable <int> customEnumerable = new UserActionEnumerable <int>(ds); Action <int> moveNextUserAction = (currentElement) => { //keep track how many times the move next of the data source was called //it is expected as //every call of MoveNext on partitioner>GetDynamicPartions.GetEnumerator //to result in only one call of datasource Move Next //there is not need to guard for concurrency issues because this scenario is single threaded dataSourceMoveNextCalls++; }; customEnumerable.MoveNextAction = moveNextUserAction; var partitioner = Partitioner.Create <int>(customEnumerable, EnumerablePartitionerOptions.NoBuffering); //get the dynamic partitions - enumerator if (isOrderable) { IEnumerator <KeyValuePair <long, int> > enumerator = partitioner.GetOrderableDynamicPartitions().GetEnumerator(); while (enumerator.MoveNext()) { Assert.Equal(dataSourceMoveNextCalls, 1); //reset the count - for the next moveNext call dataSourceMoveNextCalls = 0; } } else { IEnumerator <int> enumerator = partitioner.GetDynamicPartitions().GetEnumerator(); while (enumerator.MoveNext()) { Assert.Equal(dataSourceMoveNextCalls, 1); //reset the count - for the next moveNext call dataSourceMoveNextCalls = 0; } } }
private static void PFEDisposeEnum(int length) { List <int> ds = new List <int>(); for (int i = 0; i < length; i++) { ds.Add(i); } //this is an enumerable that will execute user actions on move next, current and dispose //in this case we will set it to wait on MoveNext for the even indexes UserActionEnumerable <int> customEnumerable = new UserActionEnumerable <int>(ds); ConcurrentQueue <int> savedDS = new ConcurrentQueue <int>(); var partitioner = Partitioner.Create <int>(customEnumerable, EnumerablePartitionerOptions.NoBuffering); Parallel.ForEach(partitioner, (index) => { savedDS.Enqueue(index); }); Assert.True(customEnumerable.AreEnumeratorsDisposed()); Assert.True(CompareCollections(savedDS, ds)); }