更新循环中属性的依赖关系

本文关键字:依赖 关系 属性 循环 更新 | 更新日期: 2023-09-27 18:16:17

我得到了一个foreach循环,在那里我更新了对象的属性。这个属性有一个依赖,我在setter中更新了它。这似乎减慢了我的应用程序,因为依赖关系需要一些时间,并且只需要在foreach循环之后更新一次。

不建议在循环之后调用依赖项的更新,因为在我的代码中的许多其他地方都使用了setter。除此之外,对象应该负责更新它的依赖项,而不是调用函数。

清晰代码示例

//anywhere else in my other classes
private Foo[] objects;
public void UpdateFoo()
{
  //update propably hundrets of small objects
  foreach (Foo obj in objects)
  {
    obj.Property = 1;
  }
}
class Foo
{
  private int _property;
  public int Property 
  { 
    get { return _property; } 
    set
    {
      _property = value;
      //Update something anywhere else
      StaticBigFoo.Update();
    } }
}
class StaticBigFoo
{
  public static void Update()
  {
    //do something longer
  }
}

我想知道这种情况下的最佳实践是什么?

  • 我可以使用DependencyProperty和它的PropertyChanged-Callback,但是依赖项仍然会每次更新。
  • 我想用DispatcherPriority.Background在Dispatcher中开始一些事情,并为不同的委托过滤它(但是如何?)
  • 我可以使用一些事务逻辑,但我不知道在那里使用什么。我读过一些关于TransactionScope的东西,我可以用它来做这样的事情吗?

更新循环中属性的依赖关系

您可以使用由几个GUI元素提供的BeginUpdate()EndUpdate()调用定义的部分。我的意思是:

class Foo
{
  private int _property;
  public int Property 
  { 
    get { return _property; } 
    set
    {
      _property = value;
      if(inUpdate)
        propertyChanged = true;
      else
        //Update something anywhere else
        StaticBigFoo.Update();
    } }
    static bool inUpdate = false;
    static bool propertyChanged;
    public static void BeginUpdate() { inUpdate = true; propertyChanged = false; }
    public static void EndUpdate() { inUpdate = false; if(propertyChanged) StaticBigFoo.Update(); }
}

Foo.BeginUpdate();    
foreach (Foo obj in objects)
{
  obj.Property = 1;
}
Foo.EndUpdate();

允许在需要时延迟更新

值得思考的是,属性主要用于以受控的方式获取/设置字段的值。或者在你的情况下,额外的一英里是变更通知。可以说,可以有验证、延迟加载。但似乎你在setter中做的比这更多,这不是最佳实践。为什么呢?因为我们可能更频繁地访问属性,这会导致对属性进行评估,从而产生底层逻辑。

我会让setter保持干净,并在其中只做字段分配和PropertyChanged。然后听PropertyChanged并在那里做额外的事情(如果你想的话,在一个单独的线程中——为了简单起见,这里使用task);

class Foo
{
 //constructor
 public Foo()
 {
    PropertyChanged += (s,args) =>
    {
       switch(args.PropertyName)
       {
          case "Property" :
            Task.Factory.StartNew(() => { StaticBigFoo.Update();});
            break;
         ....
 public int Property
 { get ...
 {
   set  
   {
      if(_property == value) return;
      _property = value;
      RaisePropertyChanged(() => Property);
    ......