ReactiveUI ViewModelViewHost 与 HandyControl 一起使用时非常慢
ReactiveUI ViewModelViewHost Is Very Slow, When using it With HandyControl
嗨,
大约 6 个月前,我开始使用反应式UI 并用它构建简单的应用程序
就在四个月前,我开始构建一个在低级别监控网络的应用程序
所以,我用 C++ 实现网络部分,然后构建 UI,并在 C# 中构建数据库模型和逻辑
然后创建一个中间库来编组这个低级 API,
如您所知,API 将提供大量数据包。
因此,在 C# 中,我决定使用响应式UI 和响应式编程,一般来说,来处理这些数据流
Rx 工作完美,使用这个高性能反应系统节省了我几天的工作时间
但是现在我遇到了一个大问题:
当我在应用程序中导航时,解析视图/ViewModel 的初始时间
太多了,平均约为 1200-506 ms
,这会导致问题,因为这会使应用程序看起来像是冻结的
所以我尝试解决这个问题,或者解决它但没有任何帮助,
我跟踪 most/all 反应式UI 的指导方针,但似乎没有任何效果
另外,请注意描述的一个奇怪行为
:
并尝试该解决方案但不起作用。
所以我尝试实现我的自定义 SimpleViewModelViewHost
SimpleViewModelViewHost.xaml
<UserControl x:Class="Sample.EnhancedViewModelViewHost"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DesignHeight="450" d:DesignWidth="800">
<ContentPresenter
x:Name="MainContent"
Content="{Binding Path=View}"
/>
</UserControl>
SimpleViewModelViewHost.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReactiveUI;
namespace Sample
{
//
/// <summary>
/// Interaction logic for EnhancedViewModelViewHost.xaml
/// </summary>
public partial class EnhancedViewModelViewHost : UserControl
{
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
"ViewModel", typeof(object), typeof(EnhancedViewModelViewHost), new PropertyMetadata(default(object)));
public object ViewModel
{
get => GetValue(ViewModelProperty);
set
{
SetValue(ViewModelProperty, value);
if (value == null) { return; }
var view = ViewLocator.Current.ResolveView(value);
if (view != null)
{
View = view;
View.ViewModel = value;
}
else
{
MainContent.Content = value;
}
}
}
public static readonly DependencyProperty ViewProperty = DependencyProperty.Register(
"View", typeof(IViewFor), typeof(EnhancedViewModelViewHost), new PropertyMetadata(default(IViewFor)));
public IViewFor View
{
get => (IViewFor)GetValue(ViewProperty);
set => SetValue(ViewProperty, value);
}
public EnhancedViewModelViewHost()
{
DataContext = this;
InitializeComponent();
}
}
}
我知道这次泄露了很多功能disposing of old view/viewModel .....
但现在性能不错:现在只需要 250-300 ms
,但仍然一点也不好
因为人眼可以注意到这种延迟
所以现在我遇到了一个大问题,所以我在 ReactiveUI 中创建了另一个带有空视图的简单应用程序
没有绑定
你猜怎么着:问题仍然存在
我使用 Visual studio 分析器来跟踪 start of a constructor of ViewModel
之间的时间
和WhenActivated in the View
的结尾
所以我的问题是:反应团队是否意识到这个问题,或者只是我做错了什么,如果是,解决方案是什么
另请注意:
我尝试通过 Creating
提高复杂布局的性能并实现一个名为 IHotReloadViewModel
的接口并实现一些逻辑以重用当前 ViewModel 而不是替换它
并获得性能 from about 1350 ms -> 10 ms
片段
视图模型的一部分
public class ManageProjectsViewModel : ReactiveObject, IActivatableViewModel
{
// .....
[Reactive] public EditProjectViewModel SelectedProject { get; set; }
//.....
private AppDbManager AppDbManager { get; set; }
#region Commands
public ReactiveCommand<Unit, Unit> EditProject { get; set; }
public ReactiveCommand<Unit, Unit> CreateNewProject { get; set; }
public ReactiveCommand<Unit, Unit> DeleteProject { get; set; }
// ....
#endregion
private IDisposable LastProjectTrack { get; set; }
private Subject<Unit> FreeSelectedProject { get; set; }
public ManageProjectsViewModel()
{
Activator = new ViewModelActivator();
AppDbManager = Locator.Current.GetService<AppDbManager>();
#region Commands
var canOperateOnProject = this.WhenValueChanged(vm => vm.SelectedProjectLookup).Select(p => p != null);
EditProject = ReactiveCommand.Create(EditProjectImpl, canOperateOnProject);
CreateNewProject = ReactiveCommand.Create(CreateNewProjectImpl);
DeleteProject = ReactiveCommand.Create(DeleteProjectImpl, canOperateOnProject);
#endregion
FreeSelectedProject = new Subject<Unit>();
this.WhenActivated(disposables =>
{
ProjectAddedNotify.ObserveOnDispatcher().Subscribe(ProjectAddedNotifyImpl).DisposeWith(disposables);
FreeSelectedProject.ObserveOnDispatcher().Subscribe(FreeSelectedProjectImpl).DisposeWith(disposables);
});
}
// ...........
View.xaml.cs
的一部分
public partial class ManageProjectsView : ReactiveUserControl<ManageProjectsViewModel>
{
private bool called = false;
public ManageProjectsView()
{
InitializeComponent();
IDisposable mainDisposable = null;
mainDisposable = this.WhenActivated(disposable =>
{
// ........
this.BindCommand(ViewModel, vm => vm.CreateNewProject, v => v.NewProject).DisposeWith(disposable);
this.BindCommand(ViewModel, vm => vm.EditProject, v => v.EditProject).DisposeWith(disposable);
this.BindCommand(ViewModel, vm => vm.DeleteProject, v => v.DeleteProject).DisposeWith(disposable);
this.Bind(ViewModel, vm => vm.SelectedProject, v => v.SelectedProject.ViewModel).DisposeWith(disposable);
ProjectLookups.Events().SelectionChanged.Subscribe(args =>
{
if (args.AddedItems.Count > 0)
{
ViewModel.SelectedProjectLookup = (NPProjectLookup)args.AddedItems[0];
}
}).DisposeWith(disposable);
ProjectLookups.ApplyHorizontalScrolling();
ProjectLookups.AllowZoom();
mainDisposable.DisposeWith(disposable);
}, this); // either use this or not: performance issue exists
}
}
大部分Views/ViewModels使用相同的结构
那么为什么我认为这是一个问题
因为我用我的 ViewModel-View Locator 的简单实现测试了相同的 UI 并且一切都立即工作
还使用 Prism With DryIoC i work with it for a long time
对其进行了测试,一切都立即有效
所以知道有什么解决方案吗,或者我需要在当前的反应式UI 应用程序中使用棱镜?
通知
- 首先我没有post在Github中的反应UI问题中这样做:因为我不想让问题面板溢出可能不必要的问题,所以我需要确定在这里,这个问题存在于其他用户设备上,如果存在,我会将其报告给 reactiveUI team
更新 (1)
在测试了多个应用后 5 apps
我发现
- 调用WhenActivated Twice的问题与reactive有关UI
- 性能问题
Delay of view
仅在将 ReactiveUI 与 HandyControl UI Library, I still can not be sure about the source of problem but because it's only happens when using HC
With RI
i decide to Create This Issue at HandyControl in GitHub 一起使用时出现
更新 (2)
请你创建一个可用的问题复制品,把它放在 github 存储库中,link 在这里,并在 https://github.com/reactiveui/ReactiveUI/issues
中创建一个问题
至于"not providing any performance considerations"的问题。在 pull request 期间有很多关于性能和影响的讨论(即 https://github.com/reactiveui/ReactiveUI/pull/1311 https://github.com/reactiveui/ReactiveUI/pull/1289 and https://github.com/reactiveui/splat/pull/360). In terms of benchmarks, indeed we're short on them, but we have an open issue https://github.com/reactiveui/ReactiveUI/issues/1734。文档可能会更好,那里有很多关于如何充分利用 ReactiveUI 的知识,欢迎人们提供帮助我们改进了使这些知识易于访问的方法。
至于对一个5000星的项目的信心。 5000 颗星很好地表明了兴趣,但 仅 兴趣。帮助维护它的人数约为 1%,其中 少数 人将他们的时间和热情花在一个项目上,有些人将近十年。他们希望人们使用该项目并希望帮助您从中获得最大收益。您想对自己使用的东西充满信心,这只是明智的,但是 有 公司在实时应用程序中使用它 and\or 每天有成千上万的用户使用的应用程序。
我可以向您指出有关 NET 框架的帖子,其星等比我们大,而且它也有 perf\knowledge\usability 个问题。但我的观点是,项目的维护者只能通过 customers\communities 尝试和反馈来学习。
对于您的实际问题,有一群人愿意提供帮助。但我们需要可重现问题的证据,最好是通过测试并可能跟踪您所看到的内容。然后我们可以协助并了解您的项目是否正在做我们可以帮助解决的事情,或者 ReactiveUI 或底层 Splat 库是否需要一些调查。
嗨,
大约 6 个月前,我开始使用反应式UI 并用它构建简单的应用程序
就在四个月前,我开始构建一个在低级别监控网络的应用程序
所以,我用 C++ 实现网络部分,然后构建 UI,并在 C# 中构建数据库模型和逻辑
然后创建一个中间库来编组这个低级 API,
如您所知,API 将提供大量数据包。
因此,在 C# 中,我决定使用响应式UI 和响应式编程,一般来说,来处理这些数据流
Rx 工作完美,使用这个高性能反应系统节省了我几天的工作时间
但是现在我遇到了一个大问题:
当我在应用程序中导航时,解析视图/ViewModel 的初始时间
太多了,平均约为 1200-506 ms
,这会导致问题,因为这会使应用程序看起来像是冻结的
所以我尝试解决这个问题,或者解决它但没有任何帮助,
我跟踪 most/all 反应式UI 的指导方针,但似乎没有任何效果
另外,请注意描述的一个奇怪行为
所以我尝试实现我的自定义 SimpleViewModelViewHost
SimpleViewModelViewHost.xaml
<UserControl x:Class="Sample.EnhancedViewModelViewHost"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DesignHeight="450" d:DesignWidth="800">
<ContentPresenter
x:Name="MainContent"
Content="{Binding Path=View}"
/>
</UserControl>
SimpleViewModelViewHost.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using ReactiveUI;
namespace Sample
{
//
/// <summary>
/// Interaction logic for EnhancedViewModelViewHost.xaml
/// </summary>
public partial class EnhancedViewModelViewHost : UserControl
{
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
"ViewModel", typeof(object), typeof(EnhancedViewModelViewHost), new PropertyMetadata(default(object)));
public object ViewModel
{
get => GetValue(ViewModelProperty);
set
{
SetValue(ViewModelProperty, value);
if (value == null) { return; }
var view = ViewLocator.Current.ResolveView(value);
if (view != null)
{
View = view;
View.ViewModel = value;
}
else
{
MainContent.Content = value;
}
}
}
public static readonly DependencyProperty ViewProperty = DependencyProperty.Register(
"View", typeof(IViewFor), typeof(EnhancedViewModelViewHost), new PropertyMetadata(default(IViewFor)));
public IViewFor View
{
get => (IViewFor)GetValue(ViewProperty);
set => SetValue(ViewProperty, value);
}
public EnhancedViewModelViewHost()
{
DataContext = this;
InitializeComponent();
}
}
}
我知道这次泄露了很多功能disposing of old view/viewModel .....
但现在性能不错:现在只需要 250-300 ms
,但仍然一点也不好
因为人眼可以注意到这种延迟
所以现在我遇到了一个大问题,所以我在 ReactiveUI 中创建了另一个带有空视图的简单应用程序
没有绑定
你猜怎么着:问题仍然存在
我使用 Visual studio 分析器来跟踪start of a constructor of ViewModel
之间的时间
和WhenActivated in the View
所以我的问题是:反应团队是否意识到这个问题,或者只是我做错了什么,如果是,解决方案是什么
另请注意:
我尝试通过 Creating
提高复杂布局的性能并实现一个名为 IHotReloadViewModel
的接口并实现一些逻辑以重用当前 ViewModel 而不是替换它
并获得性能 from about 1350 ms -> 10 ms
片段
视图模型的一部分
public class ManageProjectsViewModel : ReactiveObject, IActivatableViewModel
{
// .....
[Reactive] public EditProjectViewModel SelectedProject { get; set; }
//.....
private AppDbManager AppDbManager { get; set; }
#region Commands
public ReactiveCommand<Unit, Unit> EditProject { get; set; }
public ReactiveCommand<Unit, Unit> CreateNewProject { get; set; }
public ReactiveCommand<Unit, Unit> DeleteProject { get; set; }
// ....
#endregion
private IDisposable LastProjectTrack { get; set; }
private Subject<Unit> FreeSelectedProject { get; set; }
public ManageProjectsViewModel()
{
Activator = new ViewModelActivator();
AppDbManager = Locator.Current.GetService<AppDbManager>();
#region Commands
var canOperateOnProject = this.WhenValueChanged(vm => vm.SelectedProjectLookup).Select(p => p != null);
EditProject = ReactiveCommand.Create(EditProjectImpl, canOperateOnProject);
CreateNewProject = ReactiveCommand.Create(CreateNewProjectImpl);
DeleteProject = ReactiveCommand.Create(DeleteProjectImpl, canOperateOnProject);
#endregion
FreeSelectedProject = new Subject<Unit>();
this.WhenActivated(disposables =>
{
ProjectAddedNotify.ObserveOnDispatcher().Subscribe(ProjectAddedNotifyImpl).DisposeWith(disposables);
FreeSelectedProject.ObserveOnDispatcher().Subscribe(FreeSelectedProjectImpl).DisposeWith(disposables);
});
}
// ...........
View.xaml.cs
的一部分
public partial class ManageProjectsView : ReactiveUserControl<ManageProjectsViewModel>
{
private bool called = false;
public ManageProjectsView()
{
InitializeComponent();
IDisposable mainDisposable = null;
mainDisposable = this.WhenActivated(disposable =>
{
// ........
this.BindCommand(ViewModel, vm => vm.CreateNewProject, v => v.NewProject).DisposeWith(disposable);
this.BindCommand(ViewModel, vm => vm.EditProject, v => v.EditProject).DisposeWith(disposable);
this.BindCommand(ViewModel, vm => vm.DeleteProject, v => v.DeleteProject).DisposeWith(disposable);
this.Bind(ViewModel, vm => vm.SelectedProject, v => v.SelectedProject.ViewModel).DisposeWith(disposable);
ProjectLookups.Events().SelectionChanged.Subscribe(args =>
{
if (args.AddedItems.Count > 0)
{
ViewModel.SelectedProjectLookup = (NPProjectLookup)args.AddedItems[0];
}
}).DisposeWith(disposable);
ProjectLookups.ApplyHorizontalScrolling();
ProjectLookups.AllowZoom();
mainDisposable.DisposeWith(disposable);
}, this); // either use this or not: performance issue exists
}
}
大部分Views/ViewModels使用相同的结构
那么为什么我认为这是一个问题
因为我用我的 ViewModel-View Locator 的简单实现测试了相同的 UI 并且一切都立即工作
还使用 Prism With DryIoC i work with it for a long time
对其进行了测试,一切都立即有效
所以知道有什么解决方案吗,或者我需要在当前的反应式UI 应用程序中使用棱镜?
通知
- 首先我没有post在Github中的反应UI问题中这样做:因为我不想让问题面板溢出可能不必要的问题,所以我需要确定在这里,这个问题存在于其他用户设备上,如果存在,我会将其报告给 reactiveUI team
更新 (1)
在测试了多个应用后 5 apps
我发现
- 调用WhenActivated Twice的问题与reactive有关UI
- 性能问题
Delay of view
仅在将 ReactiveUI 与 HandyControl UI Library, I still can not be sure about the source of problem but because it's only happens when usingHC
WithRI
i decide to Create This Issue at HandyControl in GitHub 一起使用时出现
更新 (2)
请你创建一个可用的问题复制品,把它放在 github 存储库中,link 在这里,并在 https://github.com/reactiveui/ReactiveUI/issues
中创建一个问题至于"not providing any performance considerations"的问题。在 pull request 期间有很多关于性能和影响的讨论(即 https://github.com/reactiveui/ReactiveUI/pull/1311 https://github.com/reactiveui/ReactiveUI/pull/1289 and https://github.com/reactiveui/splat/pull/360). In terms of benchmarks, indeed we're short on them, but we have an open issue https://github.com/reactiveui/ReactiveUI/issues/1734。文档可能会更好,那里有很多关于如何充分利用 ReactiveUI 的知识,欢迎人们提供帮助我们改进了使这些知识易于访问的方法。
至于对一个5000星的项目的信心。 5000 颗星很好地表明了兴趣,但 仅 兴趣。帮助维护它的人数约为 1%,其中 少数 人将他们的时间和热情花在一个项目上,有些人将近十年。他们希望人们使用该项目并希望帮助您从中获得最大收益。您想对自己使用的东西充满信心,这只是明智的,但是 有 公司在实时应用程序中使用它 and\or 每天有成千上万的用户使用的应用程序。
我可以向您指出有关 NET 框架的帖子,其星等比我们大,而且它也有 perf\knowledge\usability 个问题。但我的观点是,项目的维护者只能通过 customers\communities 尝试和反馈来学习。
对于您的实际问题,有一群人愿意提供帮助。但我们需要可重现问题的证据,最好是通过测试并可能跟踪您所看到的内容。然后我们可以协助并了解您的项目是否正在做我们可以帮助解决的事情,或者 ReactiveUI 或底层 Splat 库是否需要一些调查。