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

标签 c# .net wpf

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

我有一个 WPF ItemsControl,其项的 IsSelected 属性是数据绑定(bind)到 View 模型中的相应属性。然后,我有一个计算密集型例程(在后台线程上)在所选项目上运行。问题是,如果我在更改项目的 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 事件来触发您的计算,但假设某事同时将大量项目添加到集合中,您实际上只需要在添加所有项目后进行一次计算,这样做是为了添加的每个项目都会大大降低性能。

如果另一个实例已经开始运行,我可以阻止密集任务运行,只需设置一个标志让它在完成时再运行一次,这将导致它只运行两次,即使选择了一堆东西一次全部完成,但这仍然比真正需要的时间多一倍。

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

最佳答案

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

  1. 使用任务并行库。任务管理器将决定是否启动线程。
  2. 使用阻塞队列。
  3. 重新设计界面以具有计算按钮
  4. 在第一次计算后缓存结果。

关于c# - 在进行一些密集计算之前等待多个快速属性更改事件 (C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17835582/

相关文章:

c# - 使用自定义参数取消订阅/删除事件处理程序

c# - MVC5 SQL 左连接查询

.net - 通过 .NET DateTime.Parse Culture 的所有字符串的正则表达式 en-US

c# - 从引用的程序集中读取 .resx 文件名

wpf - 如何使 WPF 中的控件调整大小等同于 Windows 窗体的 anchor /停靠属性?

c# - WPF:防止用户离开 TextBox?

c# - 如何获取 List<of anonymous type> 字段的值(加上转换)?

c# - Entity Framework 6 更新表并插入外键相关表

c# - 来自代码隐藏的按钮边框厚度

.net - 将MP3转换为Memorystream中的WAV以使用System.Media.Soundplayer进行播放