public LazyRemoteService(InteractiveHost host, InteractiveHostOptions options, int instanceId, bool skipInitialization) { InitializedService = new AsyncLazy <InitializedRemoteService>(TryStartAndInitializeProcessAsync, cacheResult: true); CancellationSource = new CancellationTokenSource(); InstanceId = instanceId; Options = options; Host = host; SkipInitialization = skipInitialization; }
// Dispose may called anytime, on any thread. internal void Dispose() { // There can be a call from host initiated from OnProcessExit. // We should not proceed with disposing if _disposeSemaphore is locked. using (_disposeSemaphore.DisposableWait()) { if (_processExitHandlerStatus == ProcessExitHandlerStatus.Hooked) { Process.Exited -= ProcessExitedHandler; _processExitHandlerStatus = ProcessExitHandlerStatus.Handled; } } InitiateTermination(Process, _processId); if (_joinOutputWritingThreadsOnDisposal) { try { _readOutputThread?.Join(); } catch (ThreadStateException) { // thread hasn't started } try { _readErrorOutputThread?.Join(); } catch (ThreadStateException) { // thread hasn't started } } // null the host so that we don't attempt to write to the buffer anymore: _host = null; _readOutputThread = _readErrorOutputThread = null; }
internal void Dispose(bool joinThreads) { // There can be a call from host initiated from OnProcessExit. // This check on the beginning helps to avoid a reentrancy. if (_processExitHandlerStatus == ProcessExitHandlerStatus.Hooked) { using (_disposeSemaphore.DisposableWait()) { if (_processExitHandlerStatus == ProcessExitHandlerStatus.Hooked) { Process.Exited -= ProcessExitedHandler; _processExitHandlerStatus = ProcessExitHandlerStatus.Handled; } } } InitiateTermination(Process, _processId); try { _readOutputThread?.Join(); } catch (ThreadStateException) { // thread hasn't started } try { _readErrorOutputThread?.Join(); } catch (ThreadStateException) { // thread hasn't started } // null the host so that we don't attempt to write to the buffer anymore: _host = null; _readOutputThread = _readErrorOutputThread = null; }
internal RemoteService(InteractiveHost host, Process process, int processId, JsonRpc jsonRpc) { Process = process; JsonRpc = jsonRpc; _host = host; _joinOutputWritingThreadsOnDisposal = _host._joinOutputWritingThreadsOnDisposal; _processId = processId; _processExitHandlerStatus = ProcessExitHandlerStatus.Uninitialized; // TODO (tomat): consider using single-thread async readers _readOutputThread = new Thread(() => ReadOutput(error: false)); _readOutputThread.Name = "InteractiveHost-OutputReader-" + processId; _readOutputThread.IsBackground = true; _readOutputThread.Start(); _readErrorOutputThread = new Thread(() => ReadOutput(error: true)); _readErrorOutputThread.Name = "InteractiveHost-ErrorOutputReader-" + processId; _readErrorOutputThread.IsBackground = true; _readErrorOutputThread.Start(); }
internal void Dispose(bool joinThreads) { // set _disposing so that we don't attempt restart the host anymore: _disposing = true; InitiateTermination(Process, _processId); // only tests require joining the threads, so we can wait synchronously if (joinThreads) { if (_readOutputThread != null) { try { _readOutputThread.Join(); } catch (ThreadStateException) { // thread hasn't started } } if (_readErrorOutputThread != null) { try { _readErrorOutputThread.Join(); } catch (ThreadStateException) { // thread hasn't started } } } // null the host so that we don't attempt to write to the buffer anymore: _host = null; _readOutputThread = _readErrorOutputThread = null; }
private InteractiveHost _host; // nulled on dispose internal RemoteService(InteractiveHost host, Process process, int processId, Service service) { Debug.Assert(host != null); Debug.Assert(process != null); Debug.Assert(service != null); _host = host; this.Process = process; _processId = processId; this.Service = service; // TODO (tomat): consider using single-thread async readers _readOutputThread = new Thread(() => ReadOutput(error: false)); _readOutputThread.Name = "InteractiveHost-OutputReader-" + processId; _readOutputThread.IsBackground = true; _readOutputThread.Start(); _readErrorOutputThread = new Thread(() => ReadOutput(error: true)); _readErrorOutputThread.Name = "InteractiveHost-ErrorOutputReader-" + processId; _readErrorOutputThread.IsBackground = true; _readErrorOutputThread.Start(); }