线程安全OfType

时间:2014-02-26 14:53:02

标签: c# multithreading

我面临的问题是这段代码:

enumerable.OfType<Foo>().Any(x => x.Footastic == true);

非线程安全并抛出枚举已更改异常。

有没有一种方法可以解决这个问题?

已经尝试了以下但它并不总是有效(似乎不经常发射)

public class Foo
{
    public void DoSomeMagicWithCollection(IEnumerable enumerable)
    {
        lock (enumerable)
        {
            enumerable.OfType<Foo>().Any(x => x.Footastic == true);
        }
    }
}

1 个答案:

答案 0 :(得分:6)

如果您在枚举时获得了底层集合已更改的异常,那么这段代码显然不会改变集合本身,这意味着当您尝试迭代它时,另一个线程正在改变集合

除了不这样做之外,没有可能解决这个问题的方法。发生的事情是List 的枚举器(或其他任何集合类型)抛出异常并阻止进一步枚举,因为它可以看到列表在枚举期间被修改。 OfType的{​​{1}}的枚举器无法将其包裹起来以便从中恢复。底层枚举器拒绝向他们提供列表中的数据。他们对此无能为力。

您需要使用某种同步机制来防止另一个线程在此线程枚举此集合时改变集合。您的Any不会阻止另一个线程使用该集合,它只是阻止任何锁定在同一实例上的代码运行。你需要有任何代码可以改变列表锁定同一个对象以正确同步它们。

另一种可能性是使用本身设计为可以同时从多个线程访问的集合。 lock命名空间中有几个这样的集合。它们可能适合您的需求,也可能不适合您他们将负责自己同步访问数据(到某一点),而无需在访问时明确锁定。