private bool TryStartClient() { var authenticationToken = Context.Next.ClientAuthenticationToken.ToString("D"); var executablePath = Context.Next.AppConfig.ClientExecutablePath; var logFilePath = $"{'"' + Context.Next.AppConfig.ClientLogFilePath + '"'}"; var logLevel = Context.Next.Settings.LogLevel.ToString(); var runtimeHostUri = Context.Next.AppConfig.RuntimeAddress; var uiMode = Context.Next.Settings.UserInterfaceMode.ToString(); var clientReady = false; var clientReadyEvent = new AutoResetEvent(false); var clientReadyEventHandler = new CommunicationEventHandler(() => clientReadyEvent.Set()); var clientTerminated = false; var clientTerminatedEventHandler = new ProcessTerminatedEventHandler(_ => { clientTerminated = true; clientReadyEvent.Set(); }); logger.Info("Starting new client process..."); runtimeHost.AllowConnection = true; runtimeHost.AuthenticationToken = Context.Next.ClientAuthenticationToken; runtimeHost.ClientReady += clientReadyEventHandler; ClientProcess = processFactory.StartNew(executablePath, logFilePath, logLevel, runtimeHostUri, authenticationToken, uiMode); ClientProcess.Terminated += clientTerminatedEventHandler; logger.Info("Waiting for client to complete initialization..."); clientReady = clientReadyEvent.WaitOne(); runtimeHost.AllowConnection = false; runtimeHost.AuthenticationToken = default(Guid?); runtimeHost.ClientReady -= clientReadyEventHandler; ClientProcess.Terminated -= clientTerminatedEventHandler; if (clientReady && !clientTerminated) { return(TryStartCommunication()); } if (!clientReady) { logger.Error($"Failed to start client!"); } if (clientTerminated) { logger.Error("Client instance terminated unexpectedly during initialization!"); } return(false); }
private bool TryStopClient() { var success = false; var disconnected = false; var disconnectedEvent = new AutoResetEvent(false); var disconnectedEventHandler = new CommunicationEventHandler(() => disconnectedEvent.Set()); var terminated = false; var terminatedEvent = new AutoResetEvent(false); var terminatedEventHandler = new ProcessTerminatedEventHandler((_) => terminatedEvent.Set()); if (ClientProxy != null) { runtimeHost.ClientDisconnected += disconnectedEventHandler; ClientProcess.Terminated += terminatedEventHandler; logger.Info("Instructing client to initiate shutdown procedure."); ClientProxy.InitiateShutdown(); logger.Info("Disconnecting from client communication host."); ClientProxy.Disconnect(); logger.Info("Waiting for client to disconnect from runtime communication host..."); disconnected = disconnectedEvent.WaitOne(timeout_ms / 2); if (!disconnected) { logger.Error($"Client failed to disconnect within {timeout_ms / 2 / 1000} seconds!"); } logger.Info("Waiting for client process to terminate..."); terminated = terminatedEvent.WaitOne(timeout_ms / 2); if (!terminated) { logger.Error($"Client failed to terminate within {timeout_ms / 2 / 1000} seconds!"); } runtimeHost.ClientDisconnected -= disconnectedEventHandler; ClientProcess.Terminated -= terminatedEventHandler; } if (disconnected && terminated) { logger.Info("Client has been successfully terminated."); success = true; } else { logger.Warn("Attempting to kill client process since graceful termination failed!"); success = TryKillClient(); } if (success) { ClientProcess = null; ClientProxy = null; } return(success); }