简体   繁体   English

如何冻结集合以便可以迭代它?

[英]How do I freeze a collection so that I can iterate through it?

The following code gives me an exception: 以下代码给了我一个例外:

var snapshot = BluetoothCapture.Instance.Snapshot();
var allowedDevice = snapshot.FirstOrDefault( _ => some_expression );

Collection was modified; 集合已修改; enumeration operation may not execute. 枚举操作可能无法执行。

I thought I could use a lock to freeze the collection so that I can iterate through it. 我以为可以使用来冻结集合,以便可以对其进行迭代。 However, I'm still getting the same exception. 但是,我仍然遇到同样的异常。

The class definition below has a Snapshot method that attempts this: 下面的类定义具有尝试执行此操作的Snapshot方法:

public partial class BluetoothCapture
{
    ...

    public void Capture()
    {
        _watcher = DeviceInformation.CreateWatcher();
        _watcher.Added += (s, e) => { _devices.Add(e); };
        _watcher.Start();
    }

    public IEnumerable<DeviceInformation> Snapshot()
    {
        lock (_devices)
        {
            return _devices.AsReadOnly();
        }
    }
}

Any suggestions? 有什么建议么?

Lock is used when you need to stop a block of code to execute in multiple threads (stop the parallel execution). 当您需要停止一个代码块以在多个线程中执行(停止并行执行)时,可以使用Lock。 If Capture is called multiple times, so, yes, you can have a write being called before the previous one being finished. 如果多次调用Capture,那么可以,可以在上一个操作完成之前调用一次写操作。

You can use a ConcurrentBag. 您可以使用ConcurrentBag。 The ConcurrentBag is a list like object, but it is thread safe (none of generic list is). ConcurrentBag是一个类似于对象的列表,但是它是线程安全的(没有通用列表)。 But, ConcurrentBag is unordered collection, so it does not guarantee ordering. 但是,ConcurrentBag是无序集合,因此不保证有序。

If you need some ordered list, you can see this link Thread safe collections in .NET 如果需要一些有序列表,则可以看到此链接。NET中的线程安全集合

You can also make a "lock" in the Add (not in the get) 您还可以在“添加”中添加“锁定”(而不是在获取中)

 _watcher.Added += (s, e) => { lock(_devices){_devices.Add(e); }};

But, if your app is running for a while, you can have a memory and performance problem (the add will be not async), even if the Capture is. 但是,如果您的应用程序运行了一段时间,那么即使Capture是运行,您也可能会遇到内存和性能问题(添加不会异步)。

lock is really very useful concept but only when we use it wisely. lock确实是非常有用的概念,但lock是我们明智地使用它。

If in further code, your don't want to update reference of snapshot (the collection which you are getting from BluetoothCapture.Instance.Snapshot() ) but just perform some Linq query to get filtered value to perform some logic. 如果在进一步的代码中,您不想更新snapshot引用(您从BluetoothCapture.Instance.Snapshot()获得的集合),而只需执行一些Linq查询以获取过滤后的值即可执行一些逻辑。 you can avoid using lock . 您可以避免使用lock

It will be beneficial too, as by not doing lock you are actually not holding other threads to perform it's logic. 这也将是有益的,因为通过不进行lock您实际上并没有持有其他线程来执行其逻辑。 - and we should not ignore the fact that terrible use of lock can cause serious problems like dead-lock too. -而且,我们也不应忽视以下事实:可怕地使用lock也会导致严重问题,例如dead-lock

you are getting this exception, most likly, the collection on which you are performing linq query; 您最有可能在执行linq查询的集合上收到此异常; is being updated by some other thread. 正在由其他线程更新。 (i too got that problem). (我也有这个问题)。

you can do one thing, instead of using general reference of collection (the one which you are getting from BluetoothCapture.Instance.Snapshot() ) you can create a local list - as it is local it will not be updated by other threads. 您可以做一件事,而不是使用collection的常规引用(从BluetoothCapture.Instance.Snapshot()获得的引用),您可以创建一个本地列表-因为它是本地列表,其他线程不会更新它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Foreach迭代集合来构建XDocument? - How can I iterate through a collection with Foreach to build an XDocument? 如何迭代数组/集合/列表中的“之间”项? - How do I iterate “between” items in an array / collection / list? 如何限制组合框中的用户输入,以便您只能输入集合中的单词? - How do I limit user input in a combobox, So that u can only type words that are within the collection? 如何从数据库中获取数据,以便可以通过JavaScript创建动态元素? - How do I fetch data from the database so I can create dynamic elements through javascript? 将属性添加到列表 <bool> 对象或类似对象,以便我可以遍历它们 - Add attributes to List<bool> objects or similar so I can iterate through them 如何使用 epplus 遍历 excel 表中的行? - How do I iterate through rows in an excel table using epplus? 如何遍历列表框中的所有项目 - How do I iterate through all the items in a listbox C#:如何分别遍历两个listBox? - C#: How do I iterate through two listBoxes individually? 如何在C#中迭代类的实例? - How do I iterate through instances of a class in C#? 如何遍历列表并检查两个对象是否相等 - How do I Iterate through a list and check if two objects are equal
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM