mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
CPU status display refactored to Rx/DynamicData
Increased the frequency of status updates to 250 milliseconds. I believe it's still low CPU usage /w the EnsureUniqueChanges call, but we can dial it back or adjust if someone else finds otherwise
This commit is contained in:
parent
9c0ace86e2
commit
1b185c5ef6
@ -8,6 +8,7 @@ using System.IO;
|
|||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Reactive.Subjects;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@ -19,6 +20,8 @@ using System.Windows.Threading;
|
|||||||
using Wabbajack.Common;
|
using Wabbajack.Common;
|
||||||
using Wabbajack.NexusApi;
|
using Wabbajack.NexusApi;
|
||||||
using Wabbajack.UI;
|
using Wabbajack.UI;
|
||||||
|
using DynamicData;
|
||||||
|
using DynamicData.Binding;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
@ -36,7 +39,8 @@ namespace Wabbajack
|
|||||||
private readonly BitmapImage _wabbajackLogo = UIUtils.BitmapImageFromResource("Wabbajack.UI.banner.png");
|
private readonly BitmapImage _wabbajackLogo = UIUtils.BitmapImageFromResource("Wabbajack.UI.banner.png");
|
||||||
public readonly BitmapImage _noneImage = UIUtils.BitmapImageFromResource("Wabbajack.UI.none.jpg");
|
public readonly BitmapImage _noneImage = UIUtils.BitmapImageFromResource("Wabbajack.UI.none.jpg");
|
||||||
|
|
||||||
public volatile bool Dirty;
|
private readonly Subject<CPUStatus> _statusSubject = new Subject<CPUStatus>();
|
||||||
|
public ObservableCollectionExtended<CPUStatus> Status { get; } = new ObservableCollectionExtended<CPUStatus>();
|
||||||
|
|
||||||
private ModList _ModList;
|
private ModList _ModList;
|
||||||
public ModList ModList { get => _ModList; private set => this.RaiseAndSetIfChanged(ref _ModList, value); }
|
public ModList ModList { get => _ModList; private set => this.RaiseAndSetIfChanged(ref _ModList, value); }
|
||||||
@ -83,7 +87,6 @@ namespace Wabbajack
|
|||||||
}
|
}
|
||||||
|
|
||||||
Mode = mode;
|
Mode = mode;
|
||||||
Dirty = false;
|
|
||||||
|
|
||||||
this.OpenReadmeCommand = ReactiveCommand.Create(
|
this.OpenReadmeCommand = ReactiveCommand.Create(
|
||||||
execute: this.OpenReadmeWindow,
|
execute: this.OpenReadmeWindow,
|
||||||
@ -159,6 +162,22 @@ namespace Wabbajack
|
|||||||
.Subscribe(_ => _slideShow.UpdateSlideShowItem())
|
.Subscribe(_ => _slideShow.UpdateSlideShowItem())
|
||||||
.DisposeWith(this.CompositeDisposable);
|
.DisposeWith(this.CompositeDisposable);
|
||||||
|
|
||||||
|
// Initialize work queue
|
||||||
|
WorkQueue.Init(
|
||||||
|
report_function: (id, msg, progress) => this._statusSubject.OnNext(new CPUStatus() { ID = id, Msg = msg, Progress = progress }),
|
||||||
|
report_queue_size: (max, current) => this.SetQueueSize(max, current));
|
||||||
|
// Compile progress updates and populate ObservableCollection
|
||||||
|
this._statusSubject
|
||||||
|
.ObserveOn(RxApp.TaskpoolScheduler)
|
||||||
|
.ToObservableChangeSet(x => x.ID)
|
||||||
|
.Batch(TimeSpan.FromMilliseconds(250))
|
||||||
|
.EnsureUniqueChanges()
|
||||||
|
.ObserveOn(RxApp.MainThreadScheduler)
|
||||||
|
.Sort(SortExpressionComparer<CPUStatus>.Ascending(s => s.ID), SortOptimisations.ComparesImmutableValuesOnly)
|
||||||
|
.Bind(this.Status)
|
||||||
|
.Subscribe()
|
||||||
|
.DisposeWith(this.CompositeDisposable);
|
||||||
|
|
||||||
slideshowThread = new Thread(UpdateLoop)
|
slideshowThread = new Thread(UpdateLoop)
|
||||||
{
|
{
|
||||||
Priority = ThreadPriority.BelowNormal,
|
Priority = ThreadPriority.BelowNormal,
|
||||||
@ -170,7 +189,6 @@ namespace Wabbajack
|
|||||||
public DateTime lastSlideShowUpdate = new DateTime();
|
public DateTime lastSlideShowUpdate = new DateTime();
|
||||||
|
|
||||||
public ObservableCollection<string> Log { get; } = new ObservableCollection<string>();
|
public ObservableCollection<string> Log { get; } = new ObservableCollection<string>();
|
||||||
public ObservableCollection<CPUStatus> Status { get; } = new ObservableCollection<CPUStatus>();
|
|
||||||
|
|
||||||
private string _Location;
|
private string _Location;
|
||||||
public string Location { get => _Location; set => this.RaiseAndSetIfChanged(ref _Location, value); }
|
public string Location { get => _Location; set => this.RaiseAndSetIfChanged(ref _Location, value); }
|
||||||
@ -198,7 +216,6 @@ namespace Wabbajack
|
|||||||
private int _queueProgress;
|
private int _queueProgress;
|
||||||
public int QueueProgress { get => _queueProgress; set => this.RaiseAndSetIfChanged(ref _queueProgress, value); }
|
public int QueueProgress { get => _queueProgress; set => this.RaiseAndSetIfChanged(ref _queueProgress, value); }
|
||||||
|
|
||||||
private List<CPUStatus> InternalStatus { get; } = new List<CPUStatus>();
|
|
||||||
public string LogFile { get; }
|
public string LogFile { get; }
|
||||||
|
|
||||||
private void ExecuteChangePath()
|
private void ExecuteChangePath()
|
||||||
@ -348,21 +365,6 @@ namespace Wabbajack
|
|||||||
{
|
{
|
||||||
while (Running)
|
while (Running)
|
||||||
{
|
{
|
||||||
if (Dirty)
|
|
||||||
lock (InternalStatus)
|
|
||||||
{
|
|
||||||
CPUStatus[] data = InternalStatus.ToArray();
|
|
||||||
Application.Current.Dispatcher.Invoke(() =>
|
|
||||||
{
|
|
||||||
for (var idx = 0; idx < data.Length; idx += 1)
|
|
||||||
if (idx >= Status.Count)
|
|
||||||
Status.Add(data[idx]);
|
|
||||||
else if (Status[idx] != data[idx])
|
|
||||||
Status[idx] = data[idx];
|
|
||||||
});
|
|
||||||
Dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_slideShow.SlidesQueue.Any())
|
if (_slideShow.SlidesQueue.Any())
|
||||||
{
|
{
|
||||||
if (DateTime.Now - lastSlideShowUpdate > TimeSpan.FromSeconds(10))
|
if (DateTime.Now - lastSlideShowUpdate > TimeSpan.FromSeconds(10))
|
||||||
@ -381,17 +383,6 @@ namespace Wabbajack
|
|||||||
Application.Current.Dispatcher.Invoke(() => Log.Add(msg));
|
Application.Current.Dispatcher.Invoke(() => Log.Add(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetProgress(int id, string msg, int progress)
|
|
||||||
{
|
|
||||||
lock (InternalStatus)
|
|
||||||
{
|
|
||||||
Dirty = true;
|
|
||||||
while (id >= InternalStatus.Count) InternalStatus.Add(new CPUStatus());
|
|
||||||
|
|
||||||
InternalStatus[id] = new CPUStatus { ID = id, Msg = msg, Progress = progress };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetQueueSize(int max, int current)
|
public void SetQueueSize(int max, int current)
|
||||||
{
|
{
|
||||||
if (max == 0)
|
if (max == 0)
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
|
using DynamicData;
|
||||||
|
using DynamicData.Kernel;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
@ -20,5 +23,54 @@ namespace Wabbajack
|
|||||||
{
|
{
|
||||||
return source.Where(u => u != null);
|
return source.Where(u => u != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// These snippets were provided by RolandPheasant (author of DynamicData)
|
||||||
|
/// They'll be going into the official library at some point, but are here for now.
|
||||||
|
#region Dynamic Data EnsureUniqueChanges
|
||||||
|
public static IObservable<IChangeSet<TObject, TKey>> EnsureUniqueChanges<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source)
|
||||||
|
{
|
||||||
|
return source.Select(EnsureUniqueChanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IChangeSet<TObject, TKey> EnsureUniqueChanges<TObject, TKey>(this IChangeSet<TObject, TKey> input)
|
||||||
|
{
|
||||||
|
var changes = input
|
||||||
|
.GroupBy(kvp => kvp.Key)
|
||||||
|
.Select(g => g.Aggregate(Optional<Change<TObject, TKey>>.None, Reduce))
|
||||||
|
.Where(x => x.HasValue)
|
||||||
|
.Select(x => x.Value);
|
||||||
|
|
||||||
|
return new ChangeSet<TObject, TKey>(changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal static Optional<Change<TObject, TKey>> Reduce<TObject, TKey>(Optional<Change<TObject, TKey>> previous, Change<TObject, TKey> next)
|
||||||
|
{
|
||||||
|
if (!previous.HasValue)
|
||||||
|
{
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
var previousValue = previous.Value;
|
||||||
|
|
||||||
|
switch (previousValue.Reason)
|
||||||
|
{
|
||||||
|
case ChangeReason.Add when next.Reason == ChangeReason.Remove:
|
||||||
|
return Optional<Change<TObject, TKey>>.None;
|
||||||
|
|
||||||
|
case ChangeReason.Remove when next.Reason == ChangeReason.Add:
|
||||||
|
return new Change<TObject, TKey>(ChangeReason.Update, next.Key, next.Current, previousValue.Current, next.CurrentIndex, previousValue.CurrentIndex);
|
||||||
|
|
||||||
|
case ChangeReason.Add when next.Reason == ChangeReason.Update:
|
||||||
|
return new Change<TObject, TKey>(ChangeReason.Add, next.Key, next.Current, next.CurrentIndex);
|
||||||
|
|
||||||
|
case ChangeReason.Update when next.Reason == ChangeReason.Update:
|
||||||
|
return new Change<TObject, TKey>(ChangeReason.Update, previousValue.Key, next.Current, previousValue.Previous, next.CurrentIndex, previousValue.PreviousIndex);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<Window
|
<Window
|
||||||
x:Class="Wabbajack.MainWindow"
|
x:Class="Wabbajack.MainWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
@ -17,7 +17,6 @@
|
|||||||
WindowStyle="ToolWindow"
|
WindowStyle="ToolWindow"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<Viewbox Stretch="Uniform">
|
<Viewbox Stretch="Uniform">
|
||||||
<!--<Grid Width="1280" Height="960">-->
|
|
||||||
<Grid Margin="4,0,4,0">
|
<Grid Margin="4,0,4,0">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
@ -25,8 +25,6 @@ namespace Wabbajack
|
|||||||
public MainWindow(RunMode mode, string source)
|
public MainWindow(RunMode mode, string source)
|
||||||
{
|
{
|
||||||
var args = Environment.GetCommandLineArgs();
|
var args = Environment.GetCommandLineArgs();
|
||||||
var DebugMode = false;
|
|
||||||
string MO2Folder = null, InstallFolder = null, MO2Profile = null;
|
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
@ -34,8 +32,6 @@ namespace Wabbajack
|
|||||||
context.LogMsg($"Wabbajack Build - {ThisAssembly.Git.Sha}");
|
context.LogMsg($"Wabbajack Build - {ThisAssembly.Git.Sha}");
|
||||||
SetupHandlers(context);
|
SetupHandlers(context);
|
||||||
DataContext = context;
|
DataContext = context;
|
||||||
WorkQueue.Init((id, msg, progress) => context.SetProgress(id, msg, progress),
|
|
||||||
(max, current) => context.SetQueueSize(max, current));
|
|
||||||
|
|
||||||
Utils.SetLoggerFn(s => context.LogMsg(s));
|
Utils.SetLoggerFn(s => context.LogMsg(s));
|
||||||
Utils.SetStatusFn((msg, progress) => WorkQueue.Report(msg, progress));
|
Utils.SetStatusFn((msg, progress) => WorkQueue.Report(msg, progress));
|
||||||
|
Loading…
Reference in New Issue
Block a user