Hi,
And just four months ago, I started to build an application that monitors the network on low level
So, I implement network part in C++ and then build UI, and database models and logic in C#
Then create an intermediate library to marshal this low-level API,
So as you know this API will provide a huge amount of packets.
and Rx works perfectly and save me days of works with this high-performance reactive system
When I navigate through the application, the initial time of resolving view / ViewModel
is so much, it's about 1200-506 ms
on average and this cause a problem because this makes the app look like its frozen
So I try to solve this problem, or get work around it but nothing helps,
I track most/all of the guidelines of reactiveUI, but nothing seems to work
in this StackOverflow question: WhenActivated is called twice: And try that solution but does not work.
SimpleViewModelViewHost
<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>
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();
}
}
}
I know this leak a lot of features disposing of old view/viewModel .....
But now performance is good: now it just takes about 250-300 ms
, but still not good at all
Because human eys can notice this delay
With no binding
and guess what: the problem still existed
I Used Visual studio profiler to track time between thestart of a constructor of ViewModel
and the end of WhenActivated in the View
Also Notice:
I try to improve the performance in complex layouts by Creating
and implement an interface called IHotReloadViewModel
and implement some logic to re-use current ViewModel instead of replacing it
and gain performance from about 1350 ms -> 10 ms
Part of ViewModel
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);
});
}
// ...........
Part of 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
}
}
Most of Views/ViewModels uses the same structure
Because I test the same UI with my simple implementation of ViewModel-View Locator and everything work instantly
Also tested it with Prism With DryIoC i work with it for a long time
and everything works instantly
so know is there any solution for that, or I will need to use a prism in the current reactiveUI app?
After testing more than one app 5 apps
i found that
Delay of view
only occurs when using ReactiveUI with 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 I Created This Issue On ReactiveUI Repository Thanks.
Can you create a usable reproduction of the issue please, put it in a github repository, link it here AND create an issue in https://github.com/reactiveui/ReactiveUI/issues
As for questions about "not providing any performance considerations". There are numerous discussions during pull requests about performance and impact (i.e. 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 for them. The documentation could be better, there is a lot of knowledge out there on how to get the best out of ReactiveUI, people are welcome to help us improve how to make that knowledge accessible.
As for confidence in a project that has 5000 stars. That 5000 stars is great as an indication of interest, but only interest. The number of people helping to maintain it equates to ~1% with a few people spending their time and passion on a project, some for almost a decade. They want people to be using the project and want to help you get the best out of it. You want confidence in what you are using which is only sensible, but there are companies using it in real-time applications and\or applications used by thousands of users everyday.
I could point you to posts about the NET framework having a magnitude of stars greater than us, and it has perf\knowledge\usability issues as well. But my point will be the maintainers of projects only learn by customers\communities trying things and feeding back.
For your actual problem, there's a team of people who are willing to help. But we need evidence in a reproducible issue, ideally with a test and possibly trace of what you're seeing. We can then assist and understand if you're project is doing something we can help solve, or whether ReactiveUI or the underlying Splat library needs some investigation.