Fix bug where event viewer may crash from a race condition, resolves #4

This commit is contained in:
BlossomiShymae
2024-08-17 16:25:37 -05:00
parent 7550102406
commit 79fd79c01d
2 changed files with 50 additions and 16 deletions

View File

@@ -18,6 +18,8 @@ namespace Needlework.Net.Desktop.ViewModels
public partial class WebsocketViewModel : PageBase
{
public ObservableCollection<string> EventLog { get; } = [];
public SemaphoreSlim EventLogLock { get; } = new(1, 1);
[NotifyPropertyChangedFor(nameof(FilteredEventLog))]
[ObservableProperty] private string _search = string.Empty;
[ObservableProperty] private bool _isAttach = true;
@@ -94,12 +96,16 @@ namespace Needlework.Net.Desktop.ViewModels
private void OnMessage(EventMessage message)
{
Avalonia.Threading.Dispatcher.UIThread.Invoke(() =>
Avalonia.Threading.Dispatcher.UIThread.Invoke(async () =>
{
if (!IsAttach) return;
var line = $"{DateTime.Now:HH:mm:ss.fff} {message.Data?.EventType.ToUpper()} {message.Data?.Uri}";
Trace.WriteLine($"Message: {line}");
await EventLogLock.WaitAsync();
try
{
if (EventLog.Count < 1000)
{
EventLog.Add(line);
@@ -114,6 +120,11 @@ namespace Needlework.Net.Desktop.ViewModels
EventLog.Add(line);
_events[line] = message;
}
}
finally
{
EventLogLock.Release();
}
});
}
}

View File

@@ -7,6 +7,7 @@ using CommunityToolkit.Mvvm.Messaging;
using Needlework.Net.Desktop.Extensions;
using Needlework.Net.Desktop.Messages;
using Needlework.Net.Desktop.ViewModels;
using System;
using TextMateSharp.Grammars;
namespace Needlework.Net.Desktop.Views;
@@ -14,6 +15,8 @@ namespace Needlework.Net.Desktop.Views;
public partial class WebsocketView : UserControl, IRecipient<ResponseUpdatedMessage>
{
private TextEditor? _responseEditor;
public WebsocketViewModel? _viewModel;
private ListBox? _viewer;
public WebsocketView()
{
@@ -29,9 +32,9 @@ public partial class WebsocketView : UserControl, IRecipient<ResponseUpdatedMess
{
base.OnApplyTemplate(e);
var vm = (WebsocketViewModel)DataContext!;
var viewer = this.FindControl<ListBox>("EventViewer");
vm.EventLog.CollectionChanged += (s, e) => { if (vm.IsTail) viewer!.ScrollIntoView(vm.EventLog.Count - 1); };
_viewModel = (WebsocketViewModel)DataContext!;
_viewer = this.FindControl<ListBox>("EventViewer");
_viewModel.EventLog.CollectionChanged += EventLog_CollectionChanged; ;
_responseEditor = this.FindControl<TextEditor>("ResponseEditor");
_responseEditor?.ApplyJsonEditorSettings();
@@ -41,6 +44,26 @@ public partial class WebsocketView : UserControl, IRecipient<ResponseUpdatedMess
OnBaseThemeChanged(Application.Current!.ActualThemeVariant);
}
private void EventLog_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
Avalonia.Threading.Dispatcher.UIThread.Post(async () =>
{
if (_viewModel!.IsTail)
{
await _viewModel.EventLogLock.WaitAsync();
try
{
_viewer!.ScrollIntoView(_viewModel.EventLog.Count - 1);
}
catch (InvalidOperationException) { }
finally
{
_viewModel.EventLogLock.Release();
}
}
});
}
private void OnBaseThemeChanged(ThemeVariant currentTheme)
{