更新不断 updated/read 的字典的正确方法?
Proper way to update a dictionary that is constantly being updated/read?
我有一个函数 returns Dictionary<uint, SomeClass>
这个函数每秒调用一次更新数据到我的列表。
现在,像这样更新我的 属性:
MyData = Api.GetData();
我的 属性 是:
public static Dictionary<uint, SomeClass> MyData { get; private set; }
- 该方法可以更新我的词典吗?应该如何完成?
我的意思是,词典一直在被 替换 ,就像现在一样,对吧?因此,如果我正在使用或更新该词典的任何条目,请说:
MyData[SomeValidKey].SomeProperty
我的参考会变成空的或无效的?或者它会简单地使用它的副本?或者这是只有根据查询 MyData 的速度等才有机会发生的事情?
什么是更新我的词典的最佳方式,同时允许我的应用程序的其他部分自由访问和使用它?
字典主要是只读的 and/or 调用字典中给定项目的函数,它是 SomeClass 的一部分。
更新:
因为MyData = Api.GetData();
意味着列表实际上被替换了?如果是这样,如果以前存在的条目不再存在但我的任何函数仍在使用它,它会导致异常吗?如果以前使用过的项目被更新,我不会有更新的数据,因为我的参考已经死了?
所以我更新词典的方式显然是错误的?
如果您在单独的线程中更新 Dictionary
,那么您应该使用适当的锁定机制来确保您正在读取当前值。 read/write 都使用 lock
。 .NET 4(或更高版本)中还有一个 ConcurrentDictionary class 是为并发操作而设计的。
但是如果你在一个线程中使用你的字典那么你根本不应该担心锁定。这是一个示例,演示当您更改对另一个 someClass 实例的引用时会发生什么:
private class SomeClass
{
public string Name { get; set; }
}
...
Dictionary<uint, SomeClass> dic = new Dictionary<uint, SomeClass>
{
{ 1u, new SomeClass { Name = "1"}},
{ 2u, new SomeClass { Name = "2"}}
};
var sc1 = dic[1]; // sc1 refers to old instance of SomeClass
dic[1] = new SomeClass { Name = "new" }; // now we change the reference here
string oldName = sc1.Name; // oldName is still "1", because sc1 points to the old instance
您的问题与您的示例不同。您的示例说明您在调用 API 时正在替换字典。你的问题对应更新
如果您要更新字典,则可以将 Api 调用的 return 分配给临时字典,然后将 transfer/add/delete 值分配给 MyData 或将 MyData 传递给您的 Api 函数并在那里处理该功能。如果从应用程序的其他部分访问,这将使您的引用保持完整。
如果这不可能,那么当您用 Api 调用替换 MyData 对象时,您不能保证代码的其他部分不会出错。此处最简单的解决方案是不缓存 MyData 条目值,而是缓存其键。然后,应用程序的其他部分可以检查其缓存的密钥是否有效并采取适当的措施。
我有一个函数 returns Dictionary<uint, SomeClass>
这个函数每秒调用一次更新数据到我的列表。
现在,像这样更新我的 属性:
MyData = Api.GetData();
我的 属性 是:
public static Dictionary<uint, SomeClass> MyData { get; private set; }
- 该方法可以更新我的词典吗?应该如何完成?
我的意思是,词典一直在被 替换 ,就像现在一样,对吧?因此,如果我正在使用或更新该词典的任何条目,请说:
MyData[SomeValidKey].SomeProperty
我的参考会变成空的或无效的?或者它会简单地使用它的副本?或者这是只有根据查询 MyData 的速度等才有机会发生的事情?
什么是更新我的词典的最佳方式,同时允许我的应用程序的其他部分自由访问和使用它?
字典主要是只读的 and/or 调用字典中给定项目的函数,它是 SomeClass 的一部分。
更新:
因为MyData = Api.GetData();
意味着列表实际上被替换了?如果是这样,如果以前存在的条目不再存在但我的任何函数仍在使用它,它会导致异常吗?如果以前使用过的项目被更新,我不会有更新的数据,因为我的参考已经死了?
所以我更新词典的方式显然是错误的?
如果您在单独的线程中更新 Dictionary
,那么您应该使用适当的锁定机制来确保您正在读取当前值。 read/write 都使用 lock
。 .NET 4(或更高版本)中还有一个 ConcurrentDictionary class 是为并发操作而设计的。
但是如果你在一个线程中使用你的字典那么你根本不应该担心锁定。这是一个示例,演示当您更改对另一个 someClass 实例的引用时会发生什么:
private class SomeClass
{
public string Name { get; set; }
}
...
Dictionary<uint, SomeClass> dic = new Dictionary<uint, SomeClass>
{
{ 1u, new SomeClass { Name = "1"}},
{ 2u, new SomeClass { Name = "2"}}
};
var sc1 = dic[1]; // sc1 refers to old instance of SomeClass
dic[1] = new SomeClass { Name = "new" }; // now we change the reference here
string oldName = sc1.Name; // oldName is still "1", because sc1 points to the old instance
您的问题与您的示例不同。您的示例说明您在调用 API 时正在替换字典。你的问题对应更新
如果您要更新字典,则可以将 Api 调用的 return 分配给临时字典,然后将 transfer/add/delete 值分配给 MyData 或将 MyData 传递给您的 Api 函数并在那里处理该功能。如果从应用程序的其他部分访问,这将使您的引用保持完整。
如果这不可能,那么当您用 Api 调用替换 MyData 对象时,您不能保证代码的其他部分不会出错。此处最简单的解决方案是不缓存 MyData 条目值,而是缓存其键。然后,应用程序的其他部分可以检查其缓存的密钥是否有效并采取适当的措施。