diff --git a/D4Companion.Services/ScreenCaptureHandler.cs b/D4Companion.Services/ScreenCaptureHandler.cs index c77dd495..2ec6d093 100644 --- a/D4Companion.Services/ScreenCaptureHandler.cs +++ b/D4Companion.Services/ScreenCaptureHandler.cs @@ -25,7 +25,6 @@ public class ScreenCaptureHandler : IScreenCaptureHandler private ScreenCapture _screenCapture = new ScreenCapture(); private int _offsetTop = 0; private int _offsetLeft = 0; - private IntPtr _windowHandle = IntPtr.Zero; // Start of Constructors region @@ -147,6 +146,10 @@ await Task.Run(() => private void UpdateScreen() { + // Note: Keep windowHandle local. On some systems making this a private class variable somehow locks the variable and prevents any garbage collection from happening. + // Memory usage jumps to 10GB+ after a few minutes. + IntPtr windowHandle = IntPtr.Zero; + bool windowFound = false; Process[] processes = new Process[0]; Process[] processesGeForceNOW = new Process[0]; @@ -157,7 +160,7 @@ private void UpdateScreen() processes = Process.GetProcessesByName("firefox"); foreach (Process p in processes) { - _windowHandle = p.MainWindowHandle; + windowHandle = p.MainWindowHandle; if (p.MainWindowTitle.StartsWith("Screenshot")) { windowFound = true; @@ -169,62 +172,58 @@ private void UpdateScreen() { IntPtr windowHandleActive = PInvoke.User32.GetForegroundWindow(); - // Only update window handle when there has been a change in active window. - if (_windowHandle == IntPtr.Zero || _windowHandle != windowHandleActive) + // Release mode - using game client + processes = Process.GetProcessesByName("Diablo IV"); + foreach (Process p in processes) { - // Release mode - using game client - processes = Process.GetProcessesByName("Diablo IV"); - foreach (Process p in processes) - { - _windowHandle = p.MainWindowHandle; - if (_windowHandle == windowHandleActive) - { - windowFound = true; - break; - } + windowHandle = p.MainWindowHandle; + if (windowHandle == windowHandleActive) + { + windowFound = true; + break; } + } - if (!windowFound) + if (!windowFound) + { + // Release mode - using GeForceNOW + processesGeForceNOW = Process.GetProcessesByName("GeForceNOW"); + foreach (Process p in processesGeForceNOW) { - // Release mode - using GeForceNOW - processesGeForceNOW = Process.GetProcessesByName("GeForceNOW"); - foreach (Process p in processesGeForceNOW) + windowHandle = p.MainWindowHandle; + if (windowHandle == windowHandleActive && p.MainWindowTitle.Contains("Diablo")) { - _windowHandle = p.MainWindowHandle; - if (_windowHandle == windowHandleActive && p.MainWindowTitle.Contains("Diablo")) - { - windowFound = true; - break; - } + windowFound = true; + break; } } + } - // Skip screencapture process when there is no active Diablo window. - if (windowHandleActive == IntPtr.Zero || windowHandleActive != _windowHandle) - { - // Reset offset used for mousecoordinates. - _offsetTop = 0; - _offsetLeft = 0; + // Skip screencapture process when there is no active Diablo window. + if (windowHandleActive == IntPtr.Zero || windowHandleActive != windowHandle) + { + // Reset offset used for mousecoordinates. + _offsetTop = 0; + _offsetLeft = 0; - // Reset screencapture. Empty screencapture will clear tooltip. - _currentScreen = null; - _eventAggregator.GetEvent().Publish(new ScreenCaptureReadyEventParams - { - CurrentScreen = _currentScreen - }); - _delayUpdateScreen = _settingsManager.Settings.ScreenCaptureDelay; - return; - } + // Reset screencapture. Empty screencapture will clear tooltip. + _currentScreen = null; + _eventAggregator.GetEvent().Publish(new ScreenCaptureReadyEventParams + { + CurrentScreen = _currentScreen + }); + _delayUpdateScreen = ScreenCaptureConstants.DelayErrorShort; + return; } } - if (_windowHandle.ToInt64() > 0) + if (windowHandle.ToInt64() > 0) { - _eventAggregator.GetEvent().Publish(new WindowHandleUpdatedEventParams { WindowHandle = _windowHandle }); + _eventAggregator.GetEvent().Publish(new WindowHandleUpdatedEventParams { WindowHandle = windowHandle }); // Update window position PInvoke.RECT region; - PInvoke.User32.GetWindowRect(_windowHandle, out region); + PInvoke.User32.GetWindowRect(windowHandle, out region); _offsetTop = region.top; _offsetLeft = region.left; @@ -232,7 +231,7 @@ private void UpdateScreen() { if (!IsScreencaptureLocked) { - _currentScreen = _screenCapture.GetScreenCapture(_windowHandle) ?? _currentScreen; + _currentScreen = _screenCapture.GetScreenCapture(windowHandle) ?? _currentScreen; //_currentScreen = new Bitmap("debug-path-to-image"); } diff --git a/D4Companion.Services/ScreenProcessHandler.cs b/D4Companion.Services/ScreenProcessHandler.cs index ead9dd2e..ddd77e3a 100644 --- a/D4Companion.Services/ScreenProcessHandler.cs +++ b/D4Companion.Services/ScreenProcessHandler.cs @@ -110,6 +110,20 @@ private void HandleScreenCaptureReadyEvent(ScreenCaptureReadyEventParams screenC if (!IsEnabled) return; if (_processTask != null && (_processTask.Status.Equals(TaskStatus.Running) || _processTask.Status.Equals(TaskStatus.WaitingForActivation))) return; + // Note: Do not move this inside ProcessScreen task. It delays the garbage collection. + // Publish empty tooltip to clear overlay when currentScreen is empty. + if (screenCaptureReadyEventParams.CurrentScreen == null) + { + _currentTooltip = new ItemTooltipDescriptor(); + _eventAggregator.GetEvent().Publish(new TooltipDataReadyEventParams + { + Tooltip = _currentTooltip + }); + + return; + } + + _processTask?.Dispose(); _processTask = Task.Run(() => ProcessScreen(screenCaptureReadyEventParams.CurrentScreen)); } @@ -240,18 +254,6 @@ private void ProcessScreen(Bitmap? currentScreen) { //_logger.LogDebug($"{MethodBase.GetCurrentMethod()?.Name}"); - // Publish empty tooltip to clear overlay when currentScreen is empty. - if (currentScreen == null) - { - _currentTooltip = new ItemTooltipDescriptor(); - _eventAggregator.GetEvent().Publish(new TooltipDataReadyEventParams - { - Tooltip = _currentTooltip - }); - - return; - } - try { var watch = System.Diagnostics.Stopwatch.StartNew(); diff --git a/D4Companion/common.props b/D4Companion/common.props index 0a7ac211..8d501426 100644 --- a/D4Companion/common.props +++ b/D4Companion/common.props @@ -1,7 +1,7 @@ - 3.8.5.0 - 3.8.5.0 + 3.8.6.0 + 3.8.6.0 Copyright © 2024 net6.0-windows