/// <nodoc/> public App(Stream clientStream, Stream serverStream, string pathToLogFile) { Contract.Requires(clientStream != null); Contract.Requires(serverStream != null); Contract.Requires(!string.IsNullOrEmpty(pathToLogFile)); ContentHashingUtilities.SetDefaultHashType(); // Note that we cannot start listening (i.e. use Attach) until // we have finished constructing the app. // Otherwise we can receive an incoming message // before we finish initialization. var jsonRpcChannel = new JsonRpcWithException(clientStream, serverStream, this); m_mainRpcChannel = jsonRpcChannel; m_mainRpcChannel.AddLocalRpcTarget(this, new JsonRpcTargetOptions { AllowNonPublicInvocation = true }); // We need to create the project management provider before we start listening on the // RPC channel as you cannot attach them after it has started listening. m_projectManagementProvider = new ProjectManagementProvider(GetAppStateDelegate(), m_mainRpcChannel); m_tracer = new Tracer(m_mainRpcChannel, pathToLogFile, EventLevel.Verbose, EventLevel.Informational); m_progressReporter = new ProgressReporter(m_mainRpcChannel, testContext: null); Logger.LanguageServerStarted(LoggingContext); Logger.LanguageServerLogFileLocation(LoggingContext, pathToLogFile); jsonRpcChannel.SetLoggingContext(Logger, LoggingContext); // Change minimal number of threads for performance reasons. // 5 is a reasonable number that should prevent thread pool exhaustion and will not spawn too many threads. ThreadPoolHelper.ConfigureWorkerThreadPools(Environment.ProcessorCount, 5); // This must be last after initialization m_mainRpcChannel.StartListening(); SubscribeToUnhandledErrors(); }