在进行一些密集计算之前等待多个快速属性更改事件(C#)

时间:2013-07-24 13:34:06

标签: c# .net wpf

我对此问题有一个特定的场景,但一个好的通用解决方案应该适用于很多情况:

我有一个WPF ItemsControl,其项目的IsSelected属性是绑定到视图模型中相应属性的数据。然后,我有一个计算密集的例程,在所选项目上运行(在后台线程上)。问题是,如果我在更改项目的IsSelected属性时触发计算密集型任务,那么当同时选择多个项目时,计算密集型任务每个项目选择运行一次,而不是仅仅一次已经选择了这些项目,这是它需要做的所有事情,因此它最终会占用比实际需要更多的处理器时间。

IEnumerable<MyObject> items;

...

void IsSelectedPropertyChangedListener(object sender, PropertyChangedEventArgs e)
{
    if(e.PropertyName == "IsSelected")
        DoSomeIntensiveCalculation(items.Where(t=>t.IsSelected));
}

void DoSomeIntensiveCalculation(IEnumerable<MyObject> itemsToCalculate)
{
    ...
}

当然我可以注册ItemsControl的SelectionChanged事件并触发它,因为即使选择了多个项目,每次选择更改只调用一次,但这有点违反MVVM,还有其他情况一个通用的解决方案可以适用,这将不会有这么简单的工作。 (如果你有一个很好的论据,为什么在这种特殊情况下我应该这样做,因为它比任何替代方案都好,我愿意听)

我能想到的另一个例子可能是你有一个ObservableCollection,你想在每次改变时计算一些困难。当然你会注册CollectionChanged事件来触发你的计算,但是假设有些东西一下子就把大量的项目添加到集合中,你真的只需要在添加所有项目后进行一次计算,添加的每个项目都会大大降低性能。

如果另一个实例已经开始运行,我可以阻止密集型任务运行,只需设置一个标志,使其在完成时再运行一次,即使选择了一堆东西,也会导致它只运行两次一下子,但这仍然是真正必要的一次。

每次启动新任务时,我都可以杀死已经运行的任务实例,但这需要在计算任务中添加大量代码,以便在请求时优雅地自行停止。它也不适用于密集型任务无法控制的情况(即它位于第三方库中,并且没有提供优雅的停止机制)。

1 个答案:

答案 0 :(得分:0)

不是100%肯定你在问什么,但这里有一些想法:

  1. 使用任务并行库。任务管理员将决定是否启动一个主题。
  2. 使用阻止队列。
  3. 重新设计界面以获得计算按钮
  4. 在第一次计算后缓存结果。