private void Close() { // Don't want output processing thread and the PollThread to go through this at the same time // If PollThread issues Dispose and the output processing thread block on the _lock below, it will cause ThreadInterruptedException // in the output processing thread if (Interlocked.CompareExchange(ref _bClosed, 1, 0) == 0) { lock (_lock) { try { _streamingShell?.Dispose(); } catch (ThreadInterruptedException) { // We will run into this when we are closing as a result of getting exit message // in OnOutputReceived method in error cases. The method will be called on the thread // that StreamingShell uses for output processing. Dispose tries to interrupt the // same thread we are on leading to ThreadInterruptedException } _streamingShell = null; } } }
private void Close() { lock (_lock) { if (_isClosed) { return; } _isClosed = true; try { if (_streamingShell != null && _streamingShell.IsOpen) { _streamingShell.Close(); } _streamingShell?.Dispose(); } catch (ThreadInterruptedException) { // This can happen if the command failed on a timeout. Say dotnet restore failed because of insufficient permissions etc. // Calling dispose on StreamingShell throws ThreadInterruptedException as well. For this case, any operation on StreamingShell // will likely cause this exception to be thrown, setting it to null to allow cleanup. } _streamingShell = null; } }
public AD7UnixAsyncCommand(IStreamingShell streamingShell, IDebugUnixShellCommandCallback callback) { _streamingShell = streamingShell; _callback = callback; Guid id = Guid.NewGuid(); _beginMessage = string.Format("Begin:{0}", id); _exitMessagePrefix = string.Format("Exit:{0}-", id); _streamingShell.OutputReceived += OnOutputReceived; _streamingShell.Closed += OnClosedOrDisconnected; _streamingShell.Disconnected += OnClosedOrDisconnected; _streamingShell.ErrorOccured += OnError; }