我正在尝试使我的应用程序线程安全。我举起手来承认我是新手,所以不知道该怎么办。
为了提供简化版本,我的应用程序包含一个列表。
第一个问题是,是否有人为此推荐过滤。
其次,我试图制作主要应用程序将使用的列表的单独副本,在更新/添加或删除某些内容时定期获取新副本,但这似乎不起作用。
我有我的清单和副本......
public class MDGlobalObjects
{
public List<T> mainList= new List<T>();
public List<T> copyList
{
get
{
return new List<T>(mainList);
}
}
}
如果我获得copyList,修改它,保存主列表,重新启动我的应用程序,加载主列表并再次查看copylist然后存在更改。我认为我做错了,因为copylist似乎仍然指的是主列表。
我不确定它是否有所作为,但所有内容都是通过类的静态实例访问的。
public static MDGlobalObjects CacheObjects = new MDGlobalObjects();
答案 0 :(得分:1)
actly copylist只是mainList的浅层副本。列表是新的,但列表中包含的对象的引用仍然是相同的。为了实现您的目标,您必须制作列表的深层副本 像这样的东西
public static IEnumerable<T> Clone<T>(this IEnumerable<T> collection) where T : ICloneable
{
return collection.Select(item => (T)item.Clone());
}
并像
一样使用它return mainList.Clone();
答案 1 :(得分:1)
ConcurrentDictionary()
时使用.Net 4.0
。因为并发集合始终保持有效状态,所以你不会使用锁
所以你的代码看起来像这样。Thread 1s code --- <br>
var object = download_the_object();
dic.TryAdd("SomeUniqueKeyOfTheObject",object);
//try add will return false so implement some sort of retry mechanism
Thread 2s code
foreach(var item in Dictionary)
{
var object item.Value;
var extraInfo = downloadExtraInfoforObject(object);
//update object by using Update
dictionary.TryUpdate(object.uniqueKey,"somenewobjectWithExtraInfoAdded",object);
}
答案 2 :(得分:1)
这是使用ConcurrentDictionary:
的要点public class Element
{
public string Key { get; set; }
public string Property { get; set; }
public Element CreateCopy()
{
return new Element
{
Key = this.Key,
Property = this.Property,
};
}
}
var d = new ConcurrentDictionary<string, Element>();
// thread 1
// prune
foreach ( var kv in d )
{
if ( kv.Value.Property == "ToBeRemoved" )
{
Element dummy = null;
d.TryRemove( kv.Key, out dummy );
}
}
// thread 1
// add
Element toBeAdded = new Element();
// set basic properties here
d.TryAdd( toBeAdded.Key, toBeAdded );
// thread 2
// populate element
Element unPopulated = null;
if ( d.TryGetValue( "ToBePopulated", out unPopulated ) )
{
Element nowPopulated = unPopulated.CreateCopy();
nowPopulated.Property = "Populated";
// either
d.TryUpdate( unPopulated.Key, nowPopulated, unPopulated );
// or
d.AddOrUpdate( unPopulated.Key, nowPopulated, ( key, value ) => nowPopulated );
}
// read threads
// enumerate
foreach ( Element element in d.Values )
{
// do something with each element
}
// read threads
// try to get specific element
Element specific = null;
if ( d.TryGetValue( "SpecificKey", out specific ) )
{
// do something with specific element
}
在线程2中,如果您可以设置属性,以便在每次原子写入后整个对象保持一致,那么您可以跳过制作副本,只需使用集合中的对象填充属性。
此代码中存在一些竞争条件,但它们应该是良性的,因为读者始终对集合有一致的视图。