diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyDiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyDiscoveryManager.cs
index ea30a418e1..f175c16789 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyDiscoveryManager.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyDiscoveryManager.cs
@@ -19,18 +19,20 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.Parallel;
///
/// ParallelProxyDiscoveryManager that manages parallel discovery
///
-internal class ParallelProxyDiscoveryManager : IParallelProxyDiscoveryManager
+internal sealed class ParallelProxyDiscoveryManager : IParallelProxyDiscoveryManager, IDisposable
{
private readonly IDataSerializer _dataSerializer;
private readonly DiscoveryDataAggregator _dataAggregator;
private readonly bool _isParallel;
private readonly ParallelOperationManager _parallelOperationManager;
private readonly Dictionary _sourceToTestHostProviderMap;
+ private readonly IRequestData _requestData;
+
private int _discoveryCompletedClients;
private int _availableTestSources;
private int _availableWorkloads;
private bool _skipDefaultAdapters;
- private readonly IRequestData _requestData;
+ private bool _isDisposed;
public bool IsAbortRequested { get; private set; }
@@ -295,4 +297,13 @@ private void DiscoverTestsOnConcurrentManager(IProxyDiscoveryManager proxyDiscov
EqtTrace.Verbose("ProxyParallelDiscoveryManager.DiscoverTestsOnConcurrentManager: No sources available for discovery.");
}
+
+ public void Dispose()
+ {
+ if (!_isDisposed)
+ {
+ _parallelOperationManager.Dispose();
+ _isDisposed = true;
+ }
+ }
}
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyExecutionManager.cs
index f0fc0969b8..09fe8eb575 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyExecutionManager.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/Parallel/ParallelProxyExecutionManager.cs
@@ -24,13 +24,15 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client.Parallel;
///
/// ParallelProxyExecutionManager that manages parallel execution
///
-internal class ParallelProxyExecutionManager : IParallelProxyExecutionManager
+internal sealed class ParallelProxyExecutionManager : IParallelProxyExecutionManager, IDisposable
{
private readonly IDataSerializer _dataSerializer;
private readonly bool _isParallel;
private readonly ParallelOperationManager _parallelOperationManager;
private readonly Dictionary _sourceToTestHostProviderMap;
+ private bool _isDisposed;
+
#region TestRunSpecificData
// This variable id to differentiate between implicit (abort requested by testPlatform) and explicit (test host aborted) abort.
@@ -405,6 +407,15 @@ private void StartTestRunOnConcurrentManager(IProxyExecutionManager proxyExecuti
EqtTrace.Verbose("ProxyParallelExecutionManager: No sources available for execution.");
}
+
+ public void Dispose()
+ {
+ if (!_isDisposed)
+ {
+ _parallelOperationManager.Dispose();
+ _isDisposed = true;
+ }
+ }
}
///
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs
index 057cb79619..96e3ea6ebe 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs
@@ -31,6 +31,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client;
///
/// Base class for any operations that the client needs to drive through the engine.
///
+[SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Would cause a breaking change if users are inheriting this class and implement IDisposable")]
public class ProxyOperationManager
{
private readonly string _versionCheckPropertyName = "IsVersionCheckRequired";
diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs
index 790bbfc12a..2d87b7b320 100644
--- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs
+++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -28,6 +29,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery;
///
/// Orchestrates discovery operations for the engine communicating with the test host process.
///
+[SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Would cause a breaking change if users are inheriting this class and implement IDisposable")]
public class DiscoveryManager : IDiscoveryManager
{
private readonly TestSessionMessageLogger _sessionMessageLogger;
diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs
index c06f0ed90f..300e5654df 100644
--- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs
+++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs
@@ -24,7 +24,7 @@ namespace Microsoft.TestPlatform.VsTestConsole.TranslationLayer;
///
/// Vstest.console process manager
///
-internal class VsTestConsoleProcessManager : IProcessManager
+internal sealed class VsTestConsoleProcessManager : IProcessManager, IDisposable
{
///
/// Port number for communicating with Vstest CLI
@@ -56,6 +56,7 @@ internal class VsTestConsoleProcessManager : IProcessManager
private Process? _process;
private bool _vstestConsoleStarted;
private bool _vstestConsoleExited;
+ private bool _isDisposed;
internal IFileHelper FileHelper { get; set; }
@@ -260,4 +261,14 @@ private string GetConsoleRunner()
private static string GetEscapeSequencedPath(string path)
=> path.IsNullOrEmpty() ? path : $"\"{path.Trim('"')}\"";
+
+ public void Dispose()
+ {
+ if (!_isDisposed)
+ {
+ _processExitedEvent.Dispose();
+ _process?.Dispose();
+ _isDisposed = true;
+ }
+ }
}