UWP多线程枚举安全的List
2024-10-21 05:56:38
最近在做windows runtime下APP开发的工作。在Service层请求返回后,往往会通过回调的形式来通知UI更新数据。多个线程操作经常出现foreach抛出异常:System.InvalidOperationException: 集合已修改;可能无法执行枚举操作,导致APP crash。
在网上搜索了一下,得出以下结论:
- 实现一个真正线程安全的List是很困难的,具体可以参考这篇Why are thread safe collections so hard?。
- 使用ConcurrentBag<T>,微软给出的线程安全的集合,缺点是unordered。如果集合依赖内部元素的顺序,就不太合适了。
- 实现一个枚举安全的List,所需的工作量相对小很多,甚至仅需要给已用到的List操作加上lock。
以下是一个最小化实现的枚举安全的List。因为实际工程中,需要枚举安全的集合仅用到了Add,Count,索引等操作,所以继承了IEnumerable接口,而不是IList。同时也不影响使用Linq to objects的扩展方法,真是偷了一个大懒。
class EnumerationSafeList<T> : IEnumerable<T>
{
private List<T> innerList = new List<T>(); private object lockObject = new object(); public IEnumerator<T> GetEnumerator()
{
return Clone().GetEnumerator();
} IEnumerator IEnumerable.GetEnumerator()
{
return Clone().GetEnumerator();
} public void Add(T item)
{
lock(lockObject)
{
innerList.Add(item);
}
} public void Remove(T item)
{
lock(lockObject)
{
innerList.Remove(item);
}
} public int Count
{
get
{
lock(lockObject)
{
return innerList.Count;
}
}
} public T this[int index]
{
get
{
lock(lockObject)
{
return innerList[index];
}
}
set
{
lock(lockObject)
{
innerList[index] = value;
}
}
} private List<T> Clone()
{
var cloneList = new List<T>();
lock(lockObject)
{
foreach (var item in innerList)
{
cloneList.Add(item);
}
}
return cloneList;
}
}
代码对Add,Remove,Count和索引四个操作加了lock,同时在枚举时通过加lock并返回当前集合的副本,来避免遍历时因为其他线程的修改而抛出异常。
如果代码需要List类型的全部方法,就需要进一步修改,把IEnumerable改成IList并实现接口,就可以得到一个完整的“data thread safe list”。
完整的代码及测试用的程序:代码
最新文章
- 针对github权限导致hexo部署失败的解决方案
- 编译器工具 Flex Bison for Windows 简单入门例子
- mysql 三种恢复方式
- 苹果手机 微信调用百度地图Javascript API 频繁闪退问题
- 耦合 Coupling the object-oriented paradigm &;&; data coupling
- ListView 使用详解
- MapReduce编程系列 — 6:多表关联
- C# using Sendkey function to send a key to another application
- java中 引用类型 和 基本类型 有何区别?
- [工作问题总结]MyEclipse 注册
- Android ReceiverCallNotAllowedException: BroadcastReceiver components are not allowed to register to receive intents
- JAVA中反射机制一
- linux命令 uname -r 和 uname -a 的解释与演示
- BZOJ_4872_[Shoi2017]分手是祝愿_概率与期望
- 正则表达式(Regular expressions)使用笔记
- Go中的iota
- Hive参数的临时设置和永久性设置
- 莫名其妙的标记之@noescape
- 几个常用的Eclipse插件
- 数据库ADO方式读取图片
热门文章
- IOS 上传ipa文件失败
- Maven(四-2) Maven pom.xml 配置详解
- 新手C#异常的学习2018.08.07
- ORA-01157:无法标识/锁定数据文件,ORA-01110:数据文件。。。
- Linux安装centos7
- 2015年传智播客JavaEE 第168期就业班视频教程17-登录功能业务逻辑实现(代码)
- ampify shader工具学习一
- iOS正确解决隐藏导航栏后push和pop或dismiss和present闪黑问题
- MVC页面和表单
- FIX protocol tutorial : Fix Session is not connecting how to diagnose it ?