Question

I have a text file containing various feeds URL's. I am reading all the URL's in a collection(IEnumerable) using following code :

var URLs = File.ReadLines(Path.GetFullPath(@"Resources\FeedList.txt"));

In the next line, I am printing the total count :

Console.WriteLine("Total Number of feeds : {0}",URLs.Count());

And after that I am using Parellel.ForEach construct, to perform some logic, corresponding to each URL. Following is the code, I am using :

Parallel.ForEach(URLs, (url) =>
                                       {
                                           // Some business logic
                                       });

The problem is, I am getting following exception, as soon as I add the code to print the number of URL's i.e. the code which calls, the Count() method on URLs object. Exception :

Total Number of feeds : 78

Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.ObjectDisposedException: Cannot read from a closed TextReader.
   at System.IO.__Error.ReaderClosed()
   at System.IO.StreamReader.ReadLine()
   at System.IO.File.<InternalReadLines>d__0.MoveNext()
   at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerator.GrabNextChunk(Int32 requestedChunkSize)
   at System.Collections.Concurrent.Partitioner.DynamicPartitionEnumerator_Abstract`2.MoveNext()
   at System.Threading.Tasks.Parallel.<>c__DisplayClass32`2.<PartitionerForEachWorker>b__30()
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
   at System.Threading.Tasks.Task.<>c__DisplayClass7.<ExecuteSelfReplicating>b__6(Object )
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWi
   at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3
   at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, Action`1 body)
   at DiscoveringGroups.Program.Main(String[] args) in C:\Users\Pawan Mishra\Documents\Visual Studio 2010\Projects\ProgrammingCollectiveIntelligence\DiscoveringGroups\Pro
Press any key to continue . . .

And if I remove/comment out the line, which prints the count value, the Parallel.ForEach loop runs fine.

Does anyone have any idea as whats going wrong in here ?

Était-ce utile?

La solution

Don't use var when you don't need to (or when the type is obviously redundant). In this case it hides what's going on, and you get surprised by the result.

The File.ReadLines method doesn't read all lines and return a collection, it returns an enumerator that reads the lines when you get items from it. The type it returns is not a string array, but an IEnumerable<string>, which you would have noticed if you had specified the type for the variable:

string[] URLs = File.ReadLines(Path.GetFullPath(@"Resources\FeedList.txt"));

This gives a compiler error, because the method doesn't return an array, so you would have seen that the result was not what you expected.

When you use the Count() method on the enumerator, it will read all the lines in the file in order to count them, so when you later on try to use the enumeration again, it has already read all lines and closed the TextReader.

Use the File.ReadAllLines method to read all lines in the file, instead of getting an enumerator:

string[] URLs = File.ReadAllLines(Path.GetFullPath(@"Resources\FeedList.txt"));

Now you can use the array multiple times.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top