I am performing a simple operation of getting a Column from DataTable. After performing this operation in Threaded environment, I am facing exception. However, I added Monitors to keep a check on the object. I still get the exception.
Exception: InvalidOperationException: Collection was modified; enumeration operation might not execute.
Error at Line : Items = result.AsEnumerable().AsParallel().Select(y => y.Field(ExtractField)).ToList();
Code Snippet:
private List<string> SomeMethod(string ExtractField)
{
List<string> Items = null;
if (Monitor.TryEnter(_locker, 100))
{
try
{
DataTable result = GetDataTable();
if (Monitor.TryEnter(_locker1, 100))
{
try
{
Items = result.AsEnumerable().AsParallel().Select(y => y.Field<string>(ExtractField)).ToList(); // ExtractFeild is the column Name
}
finally
{
Monitor.Exit(_locker1);
}
}
Items.RemoveAll(item => String.IsNullOrEmpty(item));
return Items;
}
finally
{
Monitor.Exit(_locker);
}
}
return Items;
}
Exception in detail:
System.AggregateException
HResult=0x80131500
Message=One or more errors occurred.
Source=System.Core
StackTrace:
at System.Linq.Parallel.QueryTaskGroupState.QueryEnd(Boolean userInitiatedDispose)
at System.Linq.Parallel.DefaultMergeHelper`2.System.Linq.Parallel.IMergeHelper<TInputOutput>.Execute()
at System.Linq.Parallel.MergeExecutor`1.Execute[TKey](PartitionedStream`2 partitions, Boolean ignoreOutput, ParallelMergeOptions options, TaskScheduler taskScheduler, Boolean isOrdered, CancellationState cancellationState, Int32 queryId)
at System.Linq.Parallel.PartitionedStreamMerger`1.Receive[TKey](PartitionedStream`2 partitionedStream)
at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.ChildResultsRecipient.Receive[TKey](PartitionedStream`2 inputStream)
at System.Linq.Parallel.ScanQueryOperator`1.ScanEnumerableQueryOperatorResults.GivePartitionedStream(IPartitionedStreamRecipient`1 recipient)
at System.Linq.Parallel.UnaryQueryOperator`2.UnaryQueryOperatorResults.GivePartitionedStream(IPartitionedStreamRecipient`1 recipient)
at System.Linq.Parallel.QueryOperator`1.GetOpenedEnumerator(Nullable`1 mergeOptions, Boolean suppressOrder, Boolean forEffect, QuerySettings querySettings)
at System.Linq.Parallel.QueryOpeningEnumerator`1.OpenQuery()
at System.Linq.Parallel.QueryOpeningEnumerator`1.MoveNext()
at System.Linq.ParallelEnumerable.ToList[TSource](ParallelQuery`1 source)
Please help here.
You can block other threads from modifying the collection by implementing a lock. This will essentially make the method synchronous.
private static object _lock = new object();
private List<string> SomeMethod(string ExtractField)
{
List<string> Items = null;
try
{
lock (_lock)
{
DataTable result = GetDataTable();
Items = result.AsEnumerable().AsParallel().Select(y => y.Field<string>(ExtractField)).ToList();
Items.RemoveAll(item => String.IsNullOrEmpty(item));
}
}
catch (Exception ex)
{
// ...
}
return Items;
}
User contributions licensed under CC BY-SA 3.0