Skip to content

Commit 2382c47

Browse files
committed
Reduce background refresh overhead
1 parent d0f38aa commit 2382c47

6 files changed

Lines changed: 178 additions & 73 deletions

File tree

MainWindow.Behaviors.partial.cs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,10 @@ private async Task HandleShortcutActionAsync(string actionName)
969969
{
970970
this.ShowInTaskbar = false;
971971
this.Hide();
972+
this.SuspendHiddenModeRefreshes();
973+
this.processViewModel.PauseRefresh();
974+
this.processViewModel.SetProcessViewActive(false);
975+
_ = this.performanceViewModel.SuspendBackgroundMonitoringAsync();
972976
}
973977
else
974978
{
@@ -1294,34 +1298,37 @@ protected override void OnStateChanged(EventArgs e)
12941298
{
12951299
try
12961300
{
1297-
if (this.WindowState == WindowState.Minimized && this.settingsService.Settings.MinimizeToTray)
1301+
if (this.WindowState == WindowState.Minimized)
12981302
{
1299-
this.ShowInTaskbar = false;
1300-
this.Hide();
1301-
this.systemTrayService.Show();
1303+
if (this.settingsService.Settings.MinimizeToTray)
1304+
{
1305+
this.ShowInTaskbar = false;
1306+
this.Hide();
1307+
this.systemTrayService.Show();
1308+
}
13021309

13031310
this.SuspendHiddenModeRefreshes();
13041311

1305-
// Pause process refresh when minimized to reduce resource usage
13061312
if (this.processViewModel != null)
13071313
{
13081314
this.processViewModel.PauseRefresh();
1315+
this.processViewModel.SetProcessViewActive(false);
13091316
}
13101317

13111318
if (this.performanceViewModel != null)
13121319
{
13131320
_ = this.performanceViewModel.SuspendBackgroundMonitoringAsync();
13141321
}
13151322
}
1316-
else if (this.WindowState == WindowState.Normal)
1323+
else if (this.WindowState == WindowState.Normal || this.WindowState == WindowState.Maximized)
13171324
{
13181325
this.ShowInTaskbar = true;
13191326

13201327
this.ResumeForegroundRefreshes();
13211328

1322-
// Resume process refresh when restored
13231329
if (this.processViewModel != null)
13241330
{
1331+
this.processViewModel.SetProcessViewActive(this.ProcessManagementTab.Visibility == Visibility.Visible);
13251332
this.processViewModel.ResumeRefresh();
13261333
}
13271334

@@ -1441,6 +1448,15 @@ private void ShowWindowFromTray(string? tabTag = null)
14411448
this.Focus();
14421449
this.Topmost = false;
14431450

1451+
var processViewWillBeActive = tabTag == null
1452+
? this.ProcessManagementTab.Visibility == Visibility.Visible
1453+
: string.Equals(tabTag, "Process", StringComparison.Ordinal);
1454+
1455+
this.ResumeForegroundRefreshes();
1456+
this.processViewModel.SetProcessViewActive(processViewWillBeActive);
1457+
this.processViewModel.ResumeRefresh();
1458+
_ = this.performanceViewModel.ResumeBackgroundMonitoringAsync();
1459+
14441460
if (tabTag != null)
14451461
{
14461462
_ = this.Dispatcher.InvokeAsync(() => this.SelectMainTab(tabTag));
@@ -1647,6 +1663,11 @@ private void ApplySectionVisibility(string tag)
16471663
this.NavLogs.IsActive = tag == "Logs";
16481664
this.NavTweaks.IsActive = tag == "Tweaks";
16491665
this.NavSettings.IsActive = tag == "Settings";
1666+
1667+
this.processViewModel.SetProcessViewActive(
1668+
string.Equals(tag, "Process", StringComparison.Ordinal) &&
1669+
this.IsVisible &&
1670+
this.WindowState != WindowState.Minimized);
16501671
}
16511672

16521673
private void NavMenuItem_Click(object sender, RoutedEventArgs e)
@@ -1768,4 +1789,3 @@ private void UnsubscribeSystemTrayEvents()
17681789
}
17691790
}
17701791
}
1771-

Services/ProcessFilterService.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,17 @@ private static bool IsSystemProcess(ProcessModel process)
9393
return false;
9494
}
9595

96-
return SystemProcessNames.Any(sp => process.Name.Equals(sp, StringComparison.OrdinalIgnoreCase)) ||
97-
process.Name.StartsWith("System", StringComparison.OrdinalIgnoreCase);
96+
var processName = NormalizeProcessName(process.Name);
97+
98+
return SystemProcessNames.Any(sp => processName.Equals(NormalizeProcessName(sp), StringComparison.OrdinalIgnoreCase)) ||
99+
processName.StartsWith("system", StringComparison.OrdinalIgnoreCase);
100+
}
101+
102+
private static string NormalizeProcessName(string processName)
103+
{
104+
return processName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)
105+
? processName[..^4]
106+
: processName;
98107
}
99108
}
100109
}

Services/VirtualizedProcessService.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,10 @@ public VirtualizedProcessService(
6767

6868
public async Task InitializeAsync()
6969
{
70-
this.logger.LogInformation("Initializing VirtualizedProcessService with batch size: {BatchSize}", this.Configuration.BatchSize);
70+
this.logger.LogDebug("Initializing VirtualizedProcessService with batch size: {BatchSize}", this.Configuration.BatchSize);
7171

7272
// Perform initial load to get total count
7373
await this.RefreshAllProcessesAsync(false);
74-
75-
if (this.Configuration.EnableBackgroundLoading)
76-
{
77-
this.backgroundPreloadTimer.Change(this.Configuration.RefreshInterval, this.Configuration.RefreshInterval);
78-
}
7974
}
8075

8176
public async Task<int> GetTotalProcessCountAsync(bool activeApplicationsOnly = false)
@@ -182,12 +177,17 @@ public async Task PreloadNextBatchAsync(int currentBatchIndex, bool activeApplic
182177
{
183178
try
184179
{
180+
if (!this.Configuration.EnableBackgroundLoading)
181+
{
182+
return;
183+
}
184+
185185
var batch = await this.LoadProcessBatchAsync(nextBatchIndex, activeApplicationsOnly);
186186
this.BackgroundBatchLoaded?.Invoke(this, batch);
187187
}
188188
catch (Exception ex)
189189
{
190-
this.logger.LogWarning(ex, "Failed to preload batch {BatchIndex}", nextBatchIndex);
190+
this.logger.LogDebug(ex, "Failed to preload batch {BatchIndex}", nextBatchIndex);
191191
}
192192
});
193193
}
@@ -256,7 +256,7 @@ private async Task RefreshAllProcessesAsync(bool activeApplicationsOnly)
256256
// Clear batch cache since underlying data changed
257257
this.batchCache.Clear();
258258

259-
this.logger.LogInformation("Refreshed {ProcessCount} processes", this.allProcesses.Count);
259+
this.logger.LogDebug("Refreshed {ProcessCount} processes", this.allProcesses.Count);
260260
}
261261
finally
262262
{
@@ -282,12 +282,17 @@ private async Task BackgroundPreloadCallbackAsync()
282282
{
283283
try
284284
{
285+
if (!this.Configuration.EnableBackgroundLoading)
286+
{
287+
return;
288+
}
289+
285290
// Refresh processes in background
286291
await this.RefreshAllProcessesAsync(false);
287292
}
288293
catch (Exception ex)
289294
{
290-
this.logger.LogWarning(ex, "Background process refresh failed");
295+
this.logger.LogDebug(ex, "Background process refresh failed");
291296
}
292297
}
293298

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace ThreadPilot.Core.Tests
2+
{
3+
using ThreadPilot.Models;
4+
using ThreadPilot.Services;
5+
6+
public sealed class ProcessFilterServiceTests
7+
{
8+
[Theory]
9+
[InlineData("svchost")]
10+
[InlineData("svchost.exe")]
11+
[InlineData("csrss")]
12+
[InlineData("csrss.exe")]
13+
public void FilterAndSort_HidesSystemProcesses_WithOrWithoutExeSuffix(string processName)
14+
{
15+
var service = new ProcessFilterService();
16+
var processes = new[]
17+
{
18+
new ProcessModel { Name = processName, CpuUsage = 10 },
19+
new ProcessModel { Name = "UserApp", CpuUsage = 1 },
20+
};
21+
22+
var result = service.FilterAndSort(processes, new ProcessFilterCriteria
23+
{
24+
HideSystemProcesses = true,
25+
SortMode = "Name",
26+
});
27+
28+
var remaining = Assert.Single(result);
29+
Assert.Equal("UserApp", remaining.Name);
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)