C# 更新循环中属性的依赖项

C# 更新循环中属性的依赖项,c#,wpf,callback,C#,Wpf,Callback,我得到了一个foreach循环,在这里我更新了对象的属性。这个属性有一个依赖项,我在setter中更新它。这似乎减慢了我的应用程序的速度,因为依赖关系需要一些时间,并且在foreach循环之后只需要更新一次 不建议在循环之后调用依赖项的更新,因为setter在我的代码中的许多其他地方都使用。除此之外,对象应该负责更新其依赖项,而不是调用函数 为清晰起见,代码示例 //anywhere else in my other classes private Foo[] objects; public

我得到了一个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
  }
}
我想知道这个szenario的最佳实践是什么

  • 我可以使用
    DependencyProperty
    和它的PropertyChanged回调,但是每次都会更新依赖项
  • 我考虑在DispatcherPriority.Background中使用
    DispatcherPriority.Background启动一些东西,并对其进行筛选以获得不同的委托(但是如何进行呢?)
  • 我可以使用一些事务逻辑,但我不知道在那里使用什么。我读了一些关于
    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保持干净,只在其中执行字段赋值和属性更改。然后听PropertyChanged并在那里做额外的事情(如果你愿意,在一个单独的线程中——为了简单起见,在这里使用task)


我喜欢这个,但它会为每个属性更改调用Update,尽管它在一个新任务中。另一个想法是,如果您不喜欢听所有属性更改的话。如何创建一个特定的私有事件“UpdateStaticBigFoo”,在您的属性中引发它并收听它。。同样的想法,除了现在当属性改变时它只触发一次我想我需要一些像Begin()&End()这样的事务,尽管我会像丹尼斯·莫罗佐夫说的那样重写setter以保持它干净。我会接受这个答案,可惜我不能接受你两个答案的合并版本;-)
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);
    ......