为什么没有在某些情况下foreach循环的工作? [英] Why doesn't a foreach loop work in certain cases?

查看:162
本文介绍了为什么没有在某些情况下foreach循环的工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是用foreach循环要经过数据列表工艺(去除所述数据处理一次 - 这是一个锁内)。这种方法现在再造成一个ArgumentException。

I was using a foreach loop to go through a list of data to process (removing said data once processed--this was inside a lock). This method caused an ArgumentException now and then.

接住它本来昂贵,因此我试图追查这个问题,但我无法找到答案。

Catching it would have been expensive so I tried tracking down the issue but I couldn't figure it out.

我已经转而使用一个for循环,问题似乎已经走了。有人能解释发生了什么?即使有异常消息我不太明白是什么了幕后的地方。

I have since switched to a for loop and the problem seems to have went away. Can someone explain what happened? Even with the exception message I don't quite understand what took place behind the scenes.

为什么for循环显然工作吗? ?难道我设置了foreach循环错了还是什么

Why is the for loop apparently working? Did I set up the foreach loop wrong or what?

这是一个很值得我回路是如何设置:

This is pretty much how my loops were set up:

foreach (string data in new List<string>(Foo.Requests))
{
    // Process the data.

    lock (Foo.Requests)
    {
        Foo.Requests.Remove(data);
    }
}

for (int i = 0; i < Foo.Requests.Count; i++)
{
    string data = Foo.Requests[i];

    // Process the data.

    lock (Foo.Requests)
    {
        Foo.Requests.Remove(data);
    }
}



编辑:对于*循环是在一段时间设置像这样:

The for* loop is in a while setup like so:

while (running)
{
    // [...]
}

编辑:添加了有关的要求异常的更多信息。

Added more information about the exception as requested.

System.ArgumentException: Destination array was not long enough. Check destIndex and length, and the array's lower bounds
  at System.Array.Copy (System.Array sourceArray, Int32 sourceIndex, System.Array destinationArray, Int32 destinationIndex, Int32 length) [0x00000] 
  at System.Collections.Generic.List`1[System.String].CopyTo (System.String[] array, Int32 arrayIndex) [0x00000] 
  at System.Collections.Generic.List`1[System.String].AddCollection (ICollection`1 collection) [0x00000] 
  at System.Collections.Generic.List`1[System.String]..ctor (IEnumerable`1 collection) [0x00000]

编辑:其原因锁定是,有另一个线程添加数据。此外,最终,多个线程将处理数据(因此,如果在整个安装错了,请指教)

The reason for the locking is that there is another thread adding data. Also, eventually, more than one thread will be processing data (so if the entire setup is wrong, please advise).

编辑:这是很难挑选一个很好的答案

It was hard to pick a good answer.

我发现埃里克利珀的评论值得,但他并没有真正回答(上投他的意见,无论如何)。

I found Eric Lippert's comment deserving but he didn't really answer (up-voted his comment anyhow).

帕维尔Minaev,乔尔Coehoorn和Thorarin全部答复了我喜欢和上投了反对票。 Thorarin也采取了额外的20分钟的时间写一些有用的代码。

Pavel Minaev, Joel Coehoorn and Thorarin all gave answers I liked and up-voted. Thorarin also took an extra 20 minutes to write some helpful code.

我,我可以接受所有3并使其分裂声誉,唉。

I which I could accept all 3 and have it split the reputation but alas.

帕维尔Minaev是下一个值得让他得到信贷。

Pavel Minaev is the next deserving so he gets the credit.

感谢您的帮助好人。 :)

Thanks for the help good people. :)

推荐答案

您的问题是,名单,LT的构造; T> 创建从的IEnumerable (这是你叫什么),一个新的列表不是线程安全的相对于它的参数。什么情况是,尽管这样的:

Your problem is that the constructor of List<T> that creates a new list from IEnumerable (which is what you call) isn't thread-safe with respect to its argument. What happens is that while this:

 new List<string>(Foo.Requests)

执行时,另一个线程修改 Foo.Requests 。你必须将其锁定为通话时长。

is executing, another thread changes Foo.Requests. You'll have to lock it for the duration of that call.

随着指出由Eric,另一个问题列表< T> 不能保证安全,为读者而另一个线程正在改变它读,无论是。即并发读取器是好的,但并发读写器都没有。而当你锁定你写反对对方,你也别把你读对你写。

As pointed out by Eric, another problem List<T> isn't guaranteed safe for readers to read while another thread is changing it, either. I.e. concurrent readers are okay, but concurrent reader and writer are not. And while you lock your writes against each other, you don't lock your reads against your writes.

这篇关于为什么没有在某些情况下foreach循环的工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆