国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

多線程枚舉安全的List

2019-11-14 13:54:59
字體:
來源:轉載
供稿:網友

  最近在做windows runtime下APP開發的工作。在Service層請求返回后,往往會通過回調的形式來通知UI更新數據。多個線程操作經常出現foreach拋出異常:System.InvalidOperationException: 集合已修改;可能無法執行枚舉操作,導致APP crash。

  在網上搜索了一下,得出以下結論:

  1.   實現一個真正線程安全的List是很困難的,具體可以參考這篇Why are thread safe collections so hard?。
  2.   使用ConcurrentBag<T>,微軟給出的線程安全的集合,缺點是unordered。如果集合依賴內部元素的順序,就不太合適了。
  3.   實現一個枚舉安全的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”。

  完整的代碼及測試用的程序:代碼


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 鸡西市| 鹤峰县| 柳林县| 四川省| 惠东县| 三台县| 晴隆县| 阜新市| 彭阳县| 常宁市| 彭州市| 剑河县| 余姚市| 怀远县| 苍南县| 防城港市| 时尚| 全椒县| 渑池县| 资源县| 韶山市| 龙山县| 江陵县| 图木舒克市| 乐至县| 华宁县| 沈丘县| 富蕴县| 普兰县| 山西省| 吴川市| 涪陵区| 德钦县| 遵义县| 遂昌县| 海晏县| 同心县| 哈尔滨市| 万荣县| 天峨县| 永修县|