如何序列化具有不断更新的集合的对象

时间:2016-06-28 17:36:45

标签: c# serialization collections

我有一个缓存服务,它包含多个Price对象,这些对象会在新价格增量到达时更新,有时会每秒多次。 每个对象在分配给ID的集合中保存它的各种价格。如果有人订阅特定价格,我需要在每次新价格到达时将最新价格对象序列化为JSON,以便通过RMQ发送。我遇到的问题是,在某些情况下,我在序列化时收到以下错误消息,因为新的价格已经到达并在上一个序列化期间更新了对象上的集合。

“收集已修改;枚举操作可能无法执行。”

我尝试了各种序列化对象的方法(它需要尽可能快)但我仍然遇到同样的问题。

解决此问题的最佳和最有效方法是什么,即使对象发生变化,我也可以序列化。

简化的对象是:

 //This is the collection on an object that holds the prices which are being updated
 public ConcurrentDictionary<Id, Prices> Asset{ get; set; } 

 //Class that holds the ever updating prices
 [Serializable] 
  public class Prices 
  {

      public Prices()
      {
          Prices1 = new List<PriceVolume>();
          Prices2 = new List<PriceVolume>();
       }
   }

提前感谢!

3 个答案:

答案 0 :(得分:0)

您应该创建一个深层副本并序列化副本,而不是序列化从并发字典中提取的实际对象。不幸的是,您仍然需要将代码放入互斥锁中。 ConcurrentDic仅保护您在检索项目时不会更改或删除项目,它不会在您检索到对象的引用后保护对象不受操纵。

答案 1 :(得分:0)

在序列化时,您可能会从locking元素中受益。

锁定时,锁定会阻止其他线程修改元素。

这将使操作尝试更改价格等待,直到您完成序列化以修改它们。

[Serializable]
public class Prices
{
    public string Serialize()
    {
        lock (this)
        {
            // logic for serilization here
        }
    }
}

答案 2 :(得分:0)

只是一个想法,但是如何看待序列化回调(有些人将其称为序列化挂钩)和实现 ISerializable 接口。您似乎需要对对象的序列化进行更细粒度的控制。看看这个链接:

Custom Serialization

请看以下

  • OnDeserializingAttribute (反序列化前)
  • OnDeserializedAttribute (反序列化后)
  • OnSerializingAttribute (序列化前)
  • OnSerializedAttribute (序列化后)

另请看这个链接:

Version Tolerant Serialization

您可以考虑对象是否保证在某些字段上使用 OptionalFieldAttribute NonSerializedAttribute 来控制是否需要序列化或可选地序列化。请注意使用 NonSerializedAttribute 。看看文章中提到的最佳实践(转载于此处以供参考):

  

要确保正确的版本控制行为,请在将类型从版本修改为版本时遵循以下规则:

     
      
  • 永远不要删除序列化字段

  •   
  • 如果该属性未应用于上一版本中的字段,请勿将 NonSerializedAttribute 属性应用于字段

  •   
  • 永远不要更改序列化字段的名称或类型

  •   
  • 添加新的序列化字段时,应用 OptionalFieldAttribute 属性
  •   
  • 从字段中移除 NonSerializedAttribute 属性(在以前的版本中无法序列化)时,应用 OptionalFieldAttribute 属性

  •   
  • 对于所有可选字段,使用序列化回调设置有意义的默认值,除非默认为0或null作为默认值

  •   
     

要确保类型与将来的序列化引擎兼容,请遵循以下准则:

     
      
  • 始终在 OptionalFieldAttribute 属性上正确设置VersionAdded属性
  •   
  • 避免分支版本化
  •