![](/img/trans.png)
[英]How can I iterate through a collection with Foreach to build an XDocument?
[英]How do I freeze a collection so that I can iterate through it?
以下代碼給了我一個例外:
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();
}
}
}
有什么建議么?
當您需要停止一個代碼塊以在多個線程中執行(停止並行執行)時,可以使用Lock。 如果多次調用Capture,那么可以,可以在上一個操作完成之前調用一次寫操作。
您可以使用ConcurrentBag。 ConcurrentBag是一個類似於對象的列表,但是它是線程安全的(沒有通用列表)。 但是,ConcurrentBag是無序集合,因此不保證有序。
如果需要一些有序列表,則可以看到此鏈接。NET中的線程安全集合
您還可以在“添加”中添加“鎖定”(而不是在獲取中)
_watcher.Added += (s, e) => { lock(_devices){_devices.Add(e); }};
但是,如果您的應用程序運行了一段時間,那么即使Capture是運行,您也可能會遇到內存和性能問題(添加不會異步)。
lock
確實是非常有用的概念,但lock
是我們明智地使用它。
如果在進一步的代碼中,您不想更新snapshot
引用(您從BluetoothCapture.Instance.Snapshot()
獲得的集合),而只需執行一些Linq
查詢以獲取過濾后的值即可執行一些邏輯。 您可以避免使用lock
。
這也將是有益的,因為通過不進行lock
您實際上並沒有持有其他線程來執行其邏輯。 -而且,我們也不應忽視以下事實:可怕地使用lock
也會導致嚴重問題,例如dead-lock
。
您最有可能在執行linq
查詢的集合上收到此異常; 正在由其他線程更新。 (我也有這個問題)。
您可以做一件事,而不是使用collection的常規引用(從BluetoothCapture.Instance.Snapshot()
獲得的引用),您可以創建一個本地列表-因為它是本地列表,其他線程不會更新它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.