你好,
大约 6 个月前,我开始使用 reactiveUI 并用它构建简单的应用程序
就在四个月前,我开始构建一个监控低级别网络的应用程序
因此,我在 C++ 中实现网络部分,然后在 C# 中构建 UI、数据库模型和逻辑
然后创建一个中间库来编组这个低级 API,
如您所知,此 API 将提供大量数据包。
因此,在 C# 中,我决定通常使用响应式 UI 和响应式编程来处理这些数据流
并且 Rx 完美运行,使用这个高性能反应系统为我节省了几天的工作时间
但是现在我有一个大问题:
当我浏览应用程序时,解析视图 / ViewModel 的初始时间非常长,大约1200-506 ms
是平均水平,这会导致问题,因为这会使应用程序看起来像是被冻结了
所以我尝试解决这个问题,或者解决它但没有任何帮助,
我跟踪了响应式 UI 的大部分/所有指南,但似乎没有任何效果
另外,请注意描述的奇怪行为
在这个 StackOverflow 问题中:WhenActivated 被调用两次:并尝试该解决方案但不起作用。
所以我尝试实现我的自定义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
{
// https://stackoverflow.com/questions/36433709/whenactivated-is-called-twice-when-used-in-views-and-viewmodels-hosted-in-viewmo/36813328#36813328
/// <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 Profiler 来跟踪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,一切都立即运行
还使用带有DryIoC的Prism对其进行了测试,一切都立即生效 i work with it for a long time
所以知道有什么解决方案吗,或者我需要在当前的响应式 UI 应用程序中使用棱镜?
注意
- 首先我没有在 Github 的 reactiveUI 问题中发布这个:因为我不想让问题面板溢出可能不必要的问题,所以我需要在这里确定这个问题是否存在于其他用户设备上,如果我将它报告给 reactiveUI团队
更新 (1)
在测试了多个应用程序后5 apps
,我发现
- 调用WhenActivated Twice的问题与reactiveUI有关
- 性能问题
Delay of view
仅在将 ReactiveUI 与HandyControl UI 库一起使用时发生,我仍然无法确定问题的根源,但因为它仅在使用时发生,HC
我RI
决定在 GitHub 的 HandyControl 上创建此问题
更新 (2)
我在 ReactiveUI 存储库上创建了这个问题 谢谢。