【问题标题】:Comparing the result of a long-running task to the previous result将长时间运行的任务的结果与之前的结果进行比较
【发布时间】:2012-02-21 03:10:39
【问题描述】:

我有一个 Web 服务,它返回一个复杂的数据结构,表示一个密集过程的结果。为了使服务响应,该进程在异步任务中运行。

第一次调用服务时,返回一个空数据结构并启动任务。后续的服务调用会返回缓存的数据,直到任务完成。完成后,我需要确定结果是否真的发生了变化。如果是这样,我会更新一个属性,该属性指示更新结果的日期/时间并重置缓存的数据,以便服务返回新结构。在未来的某个时刻,基于各种原因,Task 会重启,逻辑会重复。

我正在寻找最有效的方法来确定结果是否已从“缓存”数据中更改。最简单的方法是在结构中的每个对象上实现 Equals,并且基于其子对象的相等性等,使用父对象的相等性等。因此在根对象上调用 Equals 会产生所需的结果,但这需要爬取整个结构,我不确定这是最好的方法。

我还考虑从原始副本开始,并使用“IsDirty”标志来指示结构中的对象已更改,但担心复制操作可能会抵消任何性能优势。

您会使用什么方法(以及为什么)?

【问题讨论】:

    标签: .net c#-4.0 task-parallel-library


    【解决方案1】:

    我将创建一个静态方法,递归遍历 2 个实例(left 和 right)的所有属性,可以选择通过使用属性来控制它,并调用 left over right 的 equals 方法。当其中一个属性表示不等时,我们知道这两个实例是不同的。这使我能够实现最少量的比较代码,同时完全控制比较的内容和比较的方式(通过使用 [NoCompare] 等新属性标记某些属性并实现自定义相等逻辑)。

    【讨论】:

    • 为什么这比让类本身实现 Equals 并执行简单的 A == B 检查更好?
    • @SonOfPirate - 这将适用于一个简单的类,您只需检查几个字段并且仅根据您的独家描述使用。然而,默认情况下,相等性要复杂得多。尝试 new object() == new object() 你会发现它会产生 false 因为地址空间不同(即使数据完全相同)。构建一个以递归方式比较类的原语的方法不会“违反”默认行为并且更易于控制。
    • 实际上,Equals 旨在在代码中被覆盖以提供 Identity Equality,因此您认为 Equals 不是最佳使用方法是正确的。 (例如,Hashtable 使用 Equals 来确定两个项目是否相等。使用基本实现,它检查引用是否指向同一个对象,这是很少需要的行为。MS 不久前添加了 ReferenceEquals 来区分。)也就是说,我认为将“等效”标准封装在每个对象中是更好的面向对象,无论我称其为 IsSameAs 还是其他名称。
    • 换句话说,我不希望在外部类中有比较逻辑,但可以看到一个外部组件爬取对象图(遵循访问者模式)以确定整体相等性的想法.
    【解决方案2】:

    假设您为数据对象提供了等号运算符,您应该能够检查它们是否相等。

    例如:

    class CacheEntry<TCacheItem> 
    {
       TCacheItem item; 
       DateTime? lastUpated; 
    } 
    
    class MyItem
    {
       int Id; 
       string Foo; 
    
       public bool Equals(MyItem b) 
       {  
          return this.Id == b.Id && this.Foo == b.Foo;  // or something like this...
       } 
    }
    

    然后当你得到你的结果时:

       CacheEntry<MyItem> cacheEntry = ...; 
       MyItem newItem = ...; 
    
       if (cacheEntry.Item != newItem)
       { 
          cacheEntry.item = newItem; 
          cacheEntry.lastUpdated = DateTime.UtcNow; 
       }
    

    nb:省略了线程安全检查。

    【讨论】:

    • 是的,这似乎是一种简单的方法,但需要时间来爬取整个对象图以比较每个对象。
    • 我不担心线程安全,因为当我到达这一点时,两个对象都不会改变。
    • 跟进@Polity 上面的帖子,您会建议访问者处理对象图的抓取,还是将对象的子对象的相等性作为其自身相等性检查的一部分?
    • 对于您的对象,比较对象所花费的时间真的那么大吗?鉴于您正在比较一个长时间运行的任务的输出,并且您应该只需要在任务返回时执行一次。
    • 是的,我很喜欢使用相等检查(不是 Equals,而是执行值相等检查的类似方法)。我唯一的问题是我是否应该将所有子对象的平等因素纳入父对象的平等之中。换句话说,我是否有一个爬取对象图的访问者或让图具有自我意识?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多