Reputation: 169
I'm trying to print multiple PDF byte arrays. Since I need the functionality to allow users to be able to print multiple reports simultaneously, I'm using a Parallel foreach. The function gets through the first byte array fine, but on the second Dequeue I get the "Collection was modified after the enumerator was instantiated." error. How do I fix this while still allowing the users to print simultaneously?
Here's the code:
public static void PrintingQueue(Queue<byte[]> printQueue, string printer, int copies)
{
Parallel.ForEach(printQueue, (currentFile) =>
{
var printFile = printQueue.Dequeue();
PrintWithGSPrint(printFile, printer, copies);
});
}
Upvotes: 3
Views: 22808
Reputation: 803
you are trying to modify the printQueue (by calling Dequeue) within the context of a Parallel.ForEach loop. This is not safe, as it leads to concurrent modification of the collection, which is not allowed.
Try this:
public static void PrintingQueue(Queue<byte[]> printQueue, string printer, int copies)
{
List<Task> printTasks = new List<Task>();
while (printQueue.Count > 0)
{
byte[] currentFile = printQueue.Dequeue();
Task printTask = Task.Run(() => PrintWithGSPrint(currentFile, printer, copies));
printTasks.Add(printTask);
}
Task.WhenAll(printTasks).Wait();
}
public static void PrintWithGSPrint(byte[] file, string printer, int copies)
{
// Your print logic goes here
}
Upvotes: 0
Reputation: 1
In my experience, just add List.Clear() after the looping that should fix your issue.
printQueue.Clear();
Upvotes: 0
Reputation: 3255
Try this solution:
The Parallel.ForEach method gives you a parameter for each item in the queue. Use that parameter in the method to do the print. Then just clear the queue when you're done.
public static void PrintingQueue(Queue<byte[]> printQueue, string printer, int copies)
{
Parallel.ForEach(printQueue, (currentFile) =>
{
PrintWithGSPrint(currentFile, printer, copies);
});
printQueue.Clear();
}
Upvotes: 1
Reputation: 4883
The exception is telling you what is happening. As the collection is being modified, the foreach statement cannot execute correctly. With the Dequeue
method, you are removing an item from the collection in which you are iterating. Do not remove the item inside the foreach loop, just clean the collection when you have finished your task.
https://msdn.microsoft.com/en-us/library/1c8bzx97(v=vs.110).aspx
Another thing you can do, is iterate through your collection backwards using a for
statement. That way you will be able to remove the elements if it is a must. You can use this answer to see how to iterate backwards: https://stackoverflow.com/a/1582317/637840
Upvotes: 7