Skip to content

Commit 2efe920

Browse files
author
user123
committed
性能优化
1 parent db0d415 commit 2efe920

File tree

6 files changed

+169
-74
lines changed

6 files changed

+169
-74
lines changed

Services.App/MainWindow.xaml.cs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public sealed partial class MainWindow : Window
2424
private readonly LogManager _logManager;
2525
private AppWindow _appWindow;
2626
private bool _isRealExit = false;
27+
private DispatcherTimer? _refreshTimer;
28+
private bool _isLoadServicesRunning = false;
2729

2830
public ObservableCollection<Service> Services { get; } = new();
2931

@@ -61,11 +63,23 @@ public MainWindow()
6163
LoadServices();
6264
Title = "ServicesApp";
6365

64-
this.Closed += (s, e) => _serviceManager.Dispose();
66+
this.Closed += OnWindowClosed;
6567

66-
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
67-
timer.Tick += (s, e) => LoadServices(true);
68-
timer.Start();
68+
_refreshTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
69+
_refreshTimer.Tick += (s, e) => LoadServices(true);
70+
_refreshTimer.Start();
71+
}
72+
73+
private void OnWindowClosed(object sender, WindowEventArgs args)
74+
{
75+
_refreshTimer?.Stop();
76+
_refreshTimer = null;
77+
if (_serviceManager != null)
78+
{
79+
_serviceManager.ServiceUpdated -= OnServiceUpdated;
80+
_serviceManager.Dispose();
81+
}
82+
TrayIcon?.Dispose();
6983
}
7084

7185
private void InitializeTrayIcon()
@@ -136,6 +150,7 @@ public void ShowWindow()
136150
_appWindow.Show();
137151
_appWindow.MoveInZOrderAtTop();
138152
this.Activate();
153+
LoadServices(); // Refresh immediately when showing
139154
}
140155

141156
public void RealExit()
@@ -172,6 +187,12 @@ private void OnServiceUpdated(object? sender, Service service)
172187

173188
private async void LoadServices(bool silent = false)
174189
{
190+
if (_isLoadServicesRunning) return;
191+
192+
// Optimization: Do not refresh UI if window is hidden and this is an automated refresh
193+
if (silent && _appWindow != null && !_appWindow.IsVisible) return;
194+
195+
_isLoadServicesRunning = true;
175196
try
176197
{
177198
if (!silent) UpdateStatus("正在加载服务...");
@@ -205,6 +226,10 @@ private async void LoadServices(bool silent = false)
205226
{
206227
if (!silent) UpdateStatus($"加载服务失败: {ex.Message}");
207228
}
229+
finally
230+
{
231+
_isLoadServicesRunning = false;
232+
}
208233
}
209234

210235
private void OnRefreshClick(object sender, RoutedEventArgs e)

Services.Core/Services.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<Nullable>enable</Nullable>
77
<Platforms>x64</Platforms>
88
<Platform>x64</Platform>
9+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
910
</PropertyGroup>
1011

1112
<ItemGroup>

Services.Core/Services/EmbeddedServiceWrapper.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,13 @@ protected override void OnStop()
5959
{
6060
try
6161
{
62-
_process.Kill();
62+
_process.Kill(true); // Kill entire process tree
6363
_process.WaitForExit(5000);
6464
}
65-
catch { }
65+
catch (Exception ex)
66+
{
67+
WriteLog($"Error stopping process: {ex.Message}");
68+
}
6669
}
6770

6871
CloseLogWriter();

Services.Core/Services/LogManager.cs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,22 @@ public async Task<string> ReadLogAsync(string? logPath)
4444
try
4545
{
4646
using (var stream = new FileStream(logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
47-
using (var reader = new StreamReader(stream))
4847
{
4948
if (stream.Length > 100 * 1024)
5049
{
5150
stream.Seek(-100 * 1024, SeekOrigin.End);
52-
reader.ReadLine();
53-
return "... (旧日志已截断) ...\n" + await reader.ReadToEndAsync();
51+
// StreamReader buffers data, so we must seek BEFORE creating it.
52+
using (var reader = new StreamReader(stream))
53+
{
54+
await reader.ReadLineAsync(); // Discard partial line
55+
return "... (旧日志已截断) ...\n" + await reader.ReadToEndAsync();
56+
}
57+
}
58+
59+
using (var reader = new StreamReader(stream))
60+
{
61+
return await reader.ReadToEndAsync();
5462
}
55-
return await reader.ReadToEndAsync();
5663
}
5764
}
5865
catch (Exception ex)
@@ -72,18 +79,24 @@ public void CleanupOldLogs(int retentionDays = DefaultRetentionDays)
7279

7380
foreach (var file in files)
7481
{
75-
var fileInfo = new FileInfo(file);
76-
if (fileInfo.CreationTime < cutoffDate)
82+
try
7783
{
78-
try
84+
var fileInfo = new FileInfo(file);
85+
if (fileInfo.CreationTime < cutoffDate)
7986
{
8087
fileInfo.Delete();
8188
}
82-
catch { }
89+
}
90+
catch (Exception ex)
91+
{
92+
System.Diagnostics.Debug.WriteLine($"Failed to delete log {file}: {ex.Message}");
8393
}
8494
}
8595
}
86-
catch { }
96+
catch (Exception ex)
97+
{
98+
System.Diagnostics.Debug.WriteLine($"CleanupOldLogs failed: {ex.Message}");
99+
}
87100
}
88101

89102
public static int GetGlobalRetentionDays()

Services.Core/Services/ServiceMonitor.cs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,30 +89,33 @@ public class ServiceStatusEventArgs : EventArgs
8989

9090
try
9191
{
92-
uint bytesNeeded;
93-
IntPtr ptr = Marshal.AllocHGlobal(1024);
94-
try
92+
// Use stackalloc to avoid heap allocation for small buffer
93+
Span<byte> buffer = stackalloc byte[1024];
94+
unsafe
9595
{
96-
if (QueryServiceStatusEx(_hService, 0, ptr, 1024, out bytesNeeded))
96+
fixed (byte* pBuffer = buffer)
9797
{
98-
var status = Marshal.PtrToStructure<SERVICE_STATUS_PROCESS>(ptr);
99-
string statusStr = status.dwCurrentState switch
98+
uint bytesNeeded;
99+
if (QueryServiceStatusEx(_hService, 0, (IntPtr)pBuffer, 1024, out bytesNeeded))
100100
{
101-
1 => "已停止",
102-
2 => "启动中",
103-
3 => "停止中",
104-
4 => "运行中",
105-
_ => "未知"
106-
};
107-
return (statusStr, (int)status.dwProcessId);
101+
var status = Marshal.PtrToStructure<SERVICE_STATUS_PROCESS>((IntPtr)pBuffer);
102+
string statusStr = status.dwCurrentState switch
103+
{
104+
1 => "已停止",
105+
2 => "启动中",
106+
3 => "停止中",
107+
4 => "运行中",
108+
_ => "未知"
109+
};
110+
return (statusStr, (int)status.dwProcessId);
111+
}
108112
}
109113
}
110-
finally
111-
{
112-
Marshal.FreeHGlobal(ptr);
113-
}
114114
}
115-
catch { }
115+
catch (Exception ex)
116+
{
117+
System.Diagnostics.Debug.WriteLine($"GetCurrentStatus Failed: {ex.Message}");
118+
}
116119
return ("未知", 0);
117120
}
118121

0 commit comments

Comments
 (0)