c# - 如何冻结集合以便可以迭代它?
问题描述
以下代码给了我一个例外:
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();
}
}
}
有什么建议么?
解决方案
当您需要停止代码块以在多个线程中执行时使用锁定(停止并行执行)。如果 Capture 被多次调用,那么,是的,您可以在前一个完成之前调用 write。
您可以使用 ConcurrentBag。ConcurrentBag 是一个类似对象的列表,但它是线程安全的(通用列表都不是)。但是,ConcurrentBag 是无序集合,所以它不保证有序。
如果您需要一些有序列表,您可以查看此链接 Thread safe collections in .NET
您还可以在 Add 中进行“锁定”(而不是在 get 中)
_watcher.Added += (s, e) => { lock(_devices){_devices.Add(e); }};
但是,如果您的应用程序运行了一段时间,您可能会遇到内存和性能问题(添加将不是异步的),即使 Capture 是。
推荐阅读
- python - 使用队列实现链表:Python
- git - 如何将“origin/master”添加到本地仓库(可能还有远程仓库),尽管我已经可以推送到远程
- html - 所选选项中的平均答案(按字母值)
- python - 用 numpy 数组/pandas 数据框中最接近的记录替换每条记录
- rust - Rust 宏:单元类型?
- snowflake-cloud-data-platform - 角色创建问题
- mysql - 无状态 bean 内 JPQL 数据中的错误
- asp.net - Asp.Net Core Angular SPA 本地化
- android-studio - Kotlin:在片段中调用 List 和 Grid recycleView
- arduino - 液晶屏显示随机字符