修复 Q&A 页面引发的内存泄漏

添加 调试模式中启动耗时监控
This commit is contained in:
Aigio Liu
2021-04-30 18:28:33 +08:00
parent d9613c5041
commit 7d73d53759
6 changed files with 93 additions and 18 deletions
@@ -123,16 +123,31 @@ namespace System.Application.UI
public override void Initialize()
{
#if DEBUG
StartTrace.Restart("App.Initialize");
#endif
AvaloniaXamlLoader.Load(this);
#if DEBUG
StartTrace.Restart("App.LoadXAML");
#endif
Name = ThisAssembly.AssemblyTrademark;
ViewModelBase.IsInDesignMode = ApplicationLifetime == null;
if (ViewModelBase.IsInDesignMode) Startup.Init(DILevel.MainProcess);
#if DEBUG
StartTrace.Restart("App.SetP");
#endif
var windowService = IWindowService.Instance;
windowService.Init();
#if DEBUG
StartTrace.Restart("WindowService.Init");
#endif
SettingsHost.Load();
#if DEBUG
StartTrace.Restart("SettingsHost.Init");
#endif
#if !UI_DEMO
if (GeneralSettings.IsStartupAppMinimized.Value)
{
@@ -144,7 +159,9 @@ namespace System.Application.UI
Theme = (AppTheme)UISettings.Theme.Value;
UISettings.Theme.Subscribe(x => Theme = (AppTheme)x);
UISettings.Language.Subscribe(x => R.ChangeLanguage(x));
#if DEBUG
StartTrace.Restart("Theme + UISettings.Subscribe");
#endif
switch (windowService.MainWindow)
{
case AchievementWindowViewModel window:
@@ -168,6 +185,9 @@ namespace System.Application.UI
};
break;
}
#if DEBUG
StartTrace.Restart("Set MainWindow");
#endif
}
public ContextMenu? NotifyIconContextMenu { get; private set; }
+19 -2
View File
@@ -22,6 +22,9 @@ namespace System.Application.UI
[STAThread]
static int Main(string[] args)
{
#if DEBUG
StartTrace.Restart();
#endif
// 目前桌面端默认使用 SystemTextJson 如果出现兼容性问题可取消下面这行代码
// Serializable.DefaultJsonImplType = Serializable.JsonImplType.NewtonsoftJson;
IsMainProcess = args.Length == 0;
@@ -54,20 +57,34 @@ namespace System.Application.UI
}
else
{
Startup.Init(DILevel.MainProcess);
#if DEBUG
StartTrace.Restart("ProcessCheck");
#endif
Startup.Init(IsMainProcess ? DILevel.MainProcess : DILevel.Min);
#if DEBUG
StartTrace.Restart("Startup.Init");
#endif
if (IsMainProcess)
{
var appInstance = new ApplicationInstance();
if (!appInstance.IsFirst) goto exit;
}
#if DEBUG
StartTrace.Restart("ApplicationInstance");
#endif
InitCefNetApp();
#if DEBUG
StartTrace.Restart("InitCefNetApp");
#endif
if (IsMainProcess)
{
InitAvaloniaApp();
}
#if DEBUG
StartTrace.Restart("InitAvaloniaApp");
#endif
}
}
catch (Exception ex)
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<SignAssembly>false</SignAssembly>
<!--(SignAssembly)对此程序集进行签名会导致编译失败(CompileAvaloniaXamlTask)-->
@@ -0,0 +1,31 @@
#if DEBUG
using System.Diagnostics;
using System.Linq;
namespace System.Application.UI
{
/// <summary>
/// 启动耗时跟踪
/// </summary>
static class StartTrace
{
static Stopwatch? sw;
public static void Restart(string? mark = null)
{
if (sw != null)
{
sw.Stop();
var msg = $"{string.Join(" ", Environment.GetCommandLineArgs().Skip(1).Take(1))}mark: {mark}, value: {sw.ElapsedMilliseconds}";
Debug.WriteLine(msg);
Console.WriteLine(msg);
sw.Restart();
}
else
{
sw = Stopwatch.StartNew();
}
}
}
}
#endif
@@ -13,17 +13,10 @@ namespace System.Application.UI.Views
InitializeComponent();
#if DEBUG
this.AttachDevTools();
StartTrace.Restart("MainWindow.ctor");
#endif
}
public MainWindow(IWindowImpl impl) : base(impl)
{
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
}
protected override void OnClosing(CancelEventArgs e)
{
#if !UI_DEMO
@@ -1,4 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using CefNet;
using CefNet.Avalonia;
@@ -28,28 +30,40 @@ namespace System.Application.UI.Views.Pages
AvaloniaXamlLoader.Load(this);
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
Dispose();
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
Dispose();
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
// TODO: 释放托管状态(托管对象)
if (webViewQA != null)
{
((IDisposable)webViewQA).Dispose();
}
}
// TODO: 释放未托管的资源(未托管的对象)并替代终结器
// TODO: 将大型字段设置为 null
// TODO: 释放未托管的资源(未托管的对象)并替代终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}
public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}