Collection modifying problem

N

nondos

Hello



I have a thread that run loop in queue variable like this:



For each <something> as <something> in <queue variable>

Next



And the thread and the loop work fine



I have problem when i want to add something to the queue and the thread is
running i get error message "Collection was modified; enumeration operation
may not execute." Is there any way to solve this? I thought about this:

For I=1 to queue.count

Next

And when the loop end check if there's new items on queue



But I prefer if there is another solution with first loop



Thanks



P.S sorry for my English
 
A

Armin Zingler

nondos said:
Hello



I have a thread that run loop in queue variable like this:



For each <something> as <something> in <queue variable>

Next



And the thread and the loop work fine



I have problem when i want to add something to the queue and the
thread is running i get error message "Collection was modified;
enumeration operation may not execute." Is there any way to solve
this? I thought about this:

For I=1 to queue.count

Next

And when the loop end check if there's new items on queue



But I prefer if there is another solution with first loop

No. Not when using For-Each.

Even using the second loop isn't the best solution, because the loop's end
value is evaluated when starting the loop, not each time. So, If queue.count
is modified during the loop, the initial value of queue.count is the number
of iterations performed.

A Do-Loop would fit better:

Do until i>queue.count
if bla then
...
i +=1
else
remove item from queue
'no i += 1 here
end if
Loop



Armin
 
G

Guest

nondos said:
I have a thread that run loop in queue variable like this:

For each <something> as <something> in <queue variable>

Next

And the thread and the loop work fine

I have problem when i want to add something to the queue and the thread
is running i get error message "Collection was modified; enumeration
operation may not execute." Is there any way to solve this?

You should synchronise the queue using locking, so that you don't add
items while another thread is reading it.

Adding items to a queue is not a thread safe operation. If the capacity
of the queue needs to be increased, you may read elements from the queue
while the underlying array is out of sync with the head and tail indices.
I thought
about this:

For I=1 to queue.count

Next

And when the loop end check if there's new items on queue

That will only circumvent the built in protection in the collection, it
will not solve the actual problem.
But I prefer if there is another solution with first loop

If you want to add items in one thread and handle them in another, you
should dequeue the items one at a time instead of looping the items.
That way you only have to lock the queue during that dequeue operation,
not during the entire loop.

I suggest that you encapsulate the queue in a class that handles locking
when you enqueue and dequeue items. That way you can safely work with
the queue from different threads.
 
?

=?windows-1252?Q?G=F6ran_Andersson?=

Armin said:
Even using the second loop isn't the best solution, because the loop's end
value is evaluated when starting the loop, not each time. So, If
queue.count
is modified during the loop, the initial value of queue.count is the number
of iterations performed.

A Do-Loop would fit better:

Do until i>queue.count
if bla then
...
i +=1
else
remove item from queue
'no i += 1 here
end if
Loop



Armin

That's not a good solution either. Adding items to a queue is not a
thread safe operation, so what the OP really needs is some proper thread
safety, not another way of looping the items.
 
A

Armin Zingler

Göran Andersson said:
That's not a good solution either. Adding items to a queue is not a
thread safe operation, so what the OP really needs is some proper
thread safety, not another way of looping the items.


What else he does is not my problem. His problem was that modifying an
object that is used with For-Each, does not work. I have shown a general
solution to iterate through a list while it is being modified. The error he
gets is not a threading problem in first place.


Armin
 
?

=?windows-1252?Q?G=F6ran_Andersson?=

Armin said:
What else he does is not my problem. His problem was that modifying an
object that is used with For-Each, does not work. I have shown a general
solution to iterate through a list while it is being modified. The error
he gets is not a threading problem in first place.


Armin

Of course it's a threading problem. He is changing the collection in a
different thread, that's the problem.

Circumventing the built-in protection in the collection doesn't solve
the problem. It prevents the error message from the enumerator, but
instead you will read items out of sequence.

Besides, the items in a queue can't be accessed by index.
 
A

Armin Zingler

Göran Andersson said:
Of course it's a threading problem. He is changing the collection in
a different thread, that's the problem.

Can you change a collection while using For-Each if it was single-threaded?
Circumventing the built-in protection in the collection doesn't
solve the problem. It prevents the error message from the
enumerator, but instead you will read items out of sequence.

Besides, the items in a queue can't be accessed by index.


He using For-Each gave me the impression that he doesn't use
System.Collections.Queue, because I would use Enqueue/Dequeue but never
For-Each. So, if he uses his own collection/array/Ararylist/List/Whatever a
Do-Loop is the best kind of loop, IMO.

Nevertheless, you're right that thread synchronization must be done. I just
was not referring to it.


Armin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top