首页 > 解决方案 > 如何冻结集合以便可以迭代它?

问题描述

以下代码给了我一个例外:

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

收藏已修改;枚举操作可能无法执行。

我想我可以使用来冻结集合,以便我可以遍历它。但是,我仍然遇到同样的异常。

下面的类定义有一个尝试这样做的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();
        }
    }
}

有什么建议么?

标签: c#locking

解决方案


当您需要停止代码块以在多个线程中执行时使用锁定(停止并行执行)。如果 Capture 被多次调用,那么,是的,您可以在前一个完成之前调用 write。

您可以使用 ConcurrentBag。ConcurrentBag 是一个类似对象的列表,但它是线程安全的(通用列表都不是)。但是,ConcurrentBag 是无序集合,所以它不保证有序。

如果您需要一些有序列表,您可以查看此链接 Thread safe collections in .NET

您还可以在 Add 中进行“锁定”(而不是在 get 中)

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

但是,如果您的应用程序运行了一段时间,您可能会遇到内存和性能问题(添加将不是异步的),即使 Capture 是。


推荐阅读