/// <summary> /// Restarts and reinitializes the host process (or starts a new one if it is not running yet). /// </summary> /// <param name="optionsOpt">The options to initialize the new process with, or null to use the current options (or default options if the process isn't running yet).</param> public async Task <RemoteExecutionResult> ResetAsync(InteractiveHostOptions optionsOpt) { try { var options = optionsOpt ?? _lazyRemoteService?.Options ?? new InteractiveHostOptions(null, CultureInfo.CurrentUICulture); // replace the existing service with a new one: var newService = CreateRemoteService(options, skipInitialization: false); LazyRemoteService oldService = Interlocked.Exchange(ref _lazyRemoteService, newService); if (oldService != null) { oldService.Dispose(joinThreads: false); } var initializedService = await TryGetOrCreateRemoteServiceAsync(processPendingOutput : false).ConfigureAwait(false); if (initializedService.ServiceOpt == null) { return(default(RemoteExecutionResult)); } return(initializedService.InitializationResult); } catch (Exception e) when(FatalError.Report(e)) { throw ExceptionUtilities.Unreachable; } }
private void DisposeRemoteService(bool disposing) { if (_lazyRemoteService != null) { _lazyRemoteService.Dispose(disposing); _lazyRemoteService = null; } }
private async Task <InitializedRemoteService> TryGetOrCreateRemoteServiceAsync(bool processPendingOutput) { try { LazyRemoteService currentRemoteService = _lazyRemoteService; // disposed or not reset: Debug.Assert(currentRemoteService != null); for (int attempt = 0; attempt < MaxAttemptsToCreateProcess; attempt++) { var initializedService = await currentRemoteService.InitializedService.GetValueAsync(currentRemoteService.CancellationSource.Token).ConfigureAwait(false); if (initializedService.ServiceOpt != null && initializedService.ServiceOpt.Process.IsAlive()) { return(initializedService); } // Service failed to start or initialize or the process died. var newService = CreateRemoteService(currentRemoteService.Options, skipInitialization: !initializedService.InitializationResult.Success); var previousService = Interlocked.CompareExchange(ref _lazyRemoteService, newService, currentRemoteService); if (previousService == currentRemoteService) { // we replaced the service whose process we know is dead: currentRemoteService.Dispose(processPendingOutput); currentRemoteService = newService; } else { // the process was reset in between our checks, try to use the new service: newService.Dispose(joinThreads: false); currentRemoteService = previousService; } } _errorOutput.WriteLine(FeaturesResources.Unable_to_create_hosting_process); } catch (OperationCanceledException) { // The user reset the process during initialization. // The reset operation will recreate the process. } catch (Exception e) when(FatalError.Report(e)) { throw ExceptionUtilities.Unreachable; } return(default(InitializedRemoteService)); }
private void Dispose(bool joinThreads, bool disposing) { if (disposing) { GC.SuppressFinalize(this); DisposeChannel(); } if (_lazyRemoteService != null) { _lazyRemoteService.Dispose(joinThreads); _lazyRemoteService = null; } }
private async Task <IService> TryGetOrCreateRemoteServiceAsync() { ThrowIfDisposed(); try { var currentRemoteService = _lazyRemoteService; for (var attempt = 0; attempt < MaxAttemptsToCreateProcess; attempt++) { if (currentRemoteService == null) { return(null); } var initializedService = await currentRemoteService.InitializedService.Value.ConfigureAwait(false); if (initializedService != null && initializedService.Process.IsAlive()) { return(initializedService.Service); } // Service failed to start or initialize or the process died. var newService = new LazyRemoteService(this); var previousService = Interlocked.CompareExchange(ref _lazyRemoteService, newService, currentRemoteService); if (previousService == currentRemoteService) { // we replaced the service whose process we know is dead: currentRemoteService.Dispose(); currentRemoteService = newService; } else { // the process was reset in between our checks, try to use the new service: newService.Dispose(); currentRemoteService = previousService; } } } catch (OperationCanceledException) { // The user reset the process during initialization. // The reset operation will recreate the process. } return(null); }
private async Task<Service> TryGetOrCreateRemoteServiceAsync() { try { var currentRemoteService = _lazyRemoteService; // disposed or not reset: Debug.Assert(currentRemoteService != null); for (var attempt = 0; attempt < MaxAttemptsToCreateProcess; attempt++) { var initializedService = await currentRemoteService.InitializedService.Value.ConfigureAwait(false); if (initializedService != null && initializedService.Process.IsAlive()) { return initializedService.Service; } // Service failed to start or initialize or the process died. var newService = new LazyRemoteService(this); var previousService = Interlocked.CompareExchange(ref _lazyRemoteService, newService, currentRemoteService); if (previousService == currentRemoteService) { // we replaced the service whose process we know is dead: currentRemoteService.Dispose(); currentRemoteService = newService; } else { // the process was reset in between our checks, try to use the new service: newService.Dispose(); currentRemoteService = previousService; } } } catch (OperationCanceledException) { // The user reset the process during initialization. // The reset operation will recreate the process. } return null; }
public void Dispose() { _disposed = true; _lazyRemoteService?.Dispose(); _lazyRemoteService = null; }
public void Dispose() { _lazyRemoteService?.Dispose(); }