diff --git a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageDispatcher.cs b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageDispatcher.cs index d188f22c..fca31dbc 100644 --- a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageDispatcher.cs +++ b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageDispatcher.cs @@ -57,6 +57,12 @@ namespace Microsoft.SqlTools.Hosting.Protocol protected MessageWriter MessageWriter { get; private set; } + /// + /// Whether the message should be handled without blocking the main thread. + /// + public bool ParallelMessageProcessing { get; set; } + + #endregion #region Constructors @@ -305,22 +311,39 @@ namespace Microsoft.SqlTools.Hosting.Protocol if (handlerToAwait != null) { - try + if (this.ParallelMessageProcessing) { - await handlerToAwait; - } - catch (TaskCanceledException) - { - // Some tasks may be cancelled due to legitimate - // timeouts so don't let those exceptions go higher. - } - catch (Exception e) - { - if (!(e is AggregateException && ((AggregateException)e).InnerExceptions[0] is TaskCanceledException)) + // Run the task in a separate thread so that the main + // thread is not blocked. + _ = Task.Run(() => { - // Log the error but don't rethrow it to prevent any errors in the handler from crashing the service - Logger.Write(TraceEventType.Error, string.Format("An unexpected error occured in the request handler: {0}", e.ToString())); - } + _ = RunTask(handlerToAwait); + }); + } + else + { + await RunTask(handlerToAwait); + } + } + } + + private async Task RunTask(Task task) + { + try + { + await task; + } + catch (TaskCanceledException) + { + // Some tasks may be cancelled due to legitimate + // timeouts so don't let those exceptions go higher. + } + catch (Exception e) + { + if (!(e is AggregateException && ((AggregateException)e).InnerExceptions[0] is TaskCanceledException)) + { + // Log the error but don't rethrow it to prevent any errors in the handler from crashing the service + Logger.Write(TraceEventType.Error, string.Format("An unexpected error occured in the request handler: {0}", e.ToString())); } } } diff --git a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/ProtocolEndpoint.cs b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/ProtocolEndpoint.cs index 1dc64521..f043e429 100644 --- a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/ProtocolEndpoint.cs +++ b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/ProtocolEndpoint.cs @@ -44,7 +44,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol /// handlers for requests, responses, and events that are /// transmitted through the channel. /// - protected MessageDispatcher MessageDispatcher { get; set; } + internal MessageDispatcher MessageDispatcher { get; set; } /// /// Initializes an instance of the protocol server using the diff --git a/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs b/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs index e7379edb..a75ddf95 100644 --- a/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs +++ b/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs @@ -63,6 +63,9 @@ namespace Microsoft.SqlTools.Hosting.Utility case "-service-name": ServiceName = args[++i]; break; + case "-parallel-message-processing": + ParallelMessageProcessing = true; + break; default: ErrorMessage += string.Format("Unknown argument \"{0}\"" + Environment.NewLine, argName); break; @@ -131,6 +134,12 @@ namespace Microsoft.SqlTools.Hosting.Utility public bool AutoFlushLog { get; private set; } = false; + /// + /// A temporary flag to decide whether the message handling should block the main thread. + /// Eventually we will fix the issues and make this the default behavior. + /// + public bool ParallelMessageProcessing { get; private set; } = false; + public virtual void SetLocale(string locale) { try @@ -155,7 +164,7 @@ namespace Microsoft.SqlTools.Hosting.Utility // Creating cultureInfo from our given locale CultureInfo language = new CultureInfo(locale); Locale = locale; - + // Allow the system set Number Format and Date Format to be preserved when changing the locale. NumberFormatInfo NumberFormat = CultureInfo.CurrentCulture.NumberFormat; DateTimeFormatInfo DateTimeFormat = CultureInfo.CurrentCulture.DateTimeFormat; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Program.cs b/src/Microsoft.SqlTools.ServiceLayer/Program.cs index ba9ec101..a5f1e711 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Program.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Program.cs @@ -45,6 +45,7 @@ namespace Microsoft.SqlTools.ServiceLayer SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails); ServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext); + serviceHost.MessageDispatcher.ParallelMessageProcessing = commandOptions.ParallelMessageProcessing; // If this service was started by another process, then it should shutdown when that parent process does. if (commandOptions.ParentProcessId != null) @@ -58,9 +59,9 @@ namespace Microsoft.SqlTools.ServiceLayer } catch (Exception ex) { - try + try { - Logger.WriteWithCallstack(TraceEventType.Critical, $"An unhandled exception occurred: {ex}"); + Logger.WriteWithCallstack(TraceEventType.Critical, $"An unhandled exception occurred: {ex}"); } catch (Exception loggerEx) {