diff --git a/src/Compilers/Server/VBCSCompiler/IClientConnection.cs b/src/Compilers/Server/VBCSCompiler/IClientConnection.cs index 5e5274ed975d4a6782763ac12748a96f60029034..1ef0ef972a770abc6a20186f5a637e8d61b5b932 100644 --- a/src/Compilers/Server/VBCSCompiler/IClientConnection.cs +++ b/src/Compilers/Server/VBCSCompiler/IClientConnection.cs @@ -61,7 +61,8 @@ internal interface IClientConnectionHost /// /// Stop accepting new connections. It will also ensure that the last return from - /// is in a completed state. + /// is either already in a completed state, or has scheduled an + /// operation which will transition the task to a completed state. /// void EndListening(); } diff --git a/src/Compilers/Server/VBCSCompiler/ServerDispatcher.cs b/src/Compilers/Server/VBCSCompiler/ServerDispatcher.cs index 9aae7267fa4c0e873c26dd4ea6355f4ab5384abe..edfe47f79491c937081a12f603c99d5a90df3964 100644 --- a/src/Compilers/Server/VBCSCompiler/ServerDispatcher.cs +++ b/src/Compilers/Server/VBCSCompiler/ServerDispatcher.cs @@ -102,20 +102,28 @@ public void ListenAndDispatchConnections(TimeSpan? keepAlive, CancellationToken _clientConnectionHost.EndListening(); } - // This type is responsible for cleaning up resources associated with _listenTask. Once EndListening - // is complete this task is guaranteed to be completed. If it ran to completion we need to - // dispose of the value. - Console.WriteLine(_listenTask?.Status); - Debug.Assert(_listenTask is null || _listenTask.IsCompleted); - if (_listenTask?.Status == TaskStatus.RanToCompletion) + if (_listenTask is not null) { - try + // This type is responsible for cleaning up resources associated with _listenTask. Once EndListening + // is complete this task is guaranteed to be either completed or have a task scheduled to complete + // it. If it ran to completion we need to dispose of the value. + if (!_listenTask.IsCompleted) { - _listenTask.Result.Dispose(); + // Wait for the task to complete + _listenTask.ContinueWith(_ => { }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default) + .Wait(CancellationToken.None); } - catch (Exception ex) + + if (_listenTask.Status == TaskStatus.RanToCompletion) { - CompilerServerLogger.LogException(ex, $"Error disposing of {nameof(_listenTask)}"); + try + { + _listenTask.Result.Dispose(); + } + catch (Exception ex) + { + CompilerServerLogger.LogException(ex, $"Error disposing of {nameof(_listenTask)}"); + } } } }