/// <summary> /// Stop the pipeline synchronously /// </summary> public override void Stop() { bool isAlreadyStopping = false; if (CanStopPipeline(out isAlreadyStopping)) { // A pipeline can be stopped before it is started.so protecting against that if (_powershell != null) { IAsyncResult asyncresult = null; try { asyncresult = _powershell.BeginStop(null, null); } catch (ObjectDisposedException) { throw PSTraceSource.NewObjectDisposedException("Pipeline"); }; asyncresult.AsyncWaitHandle.WaitOne(); } } // Waits until pipeline completes stop as this is a sync call. PipelineFinishedEvent.WaitOne(); }
/// <summary> /// Does the cleanup necessary on pipeline completion /// </summary> private void Cleanup() { //Close the output stream if it is not closed. if (_outputStream.IsOpen) { try { _outputCollection.Complete(); _outputStream.Close(); } catch (ObjectDisposedException) { } } //Close the error stream if it is not closed. if (_errorStream.IsOpen) { try { _errorCollection.Complete(); _errorStream.Close(); } catch (ObjectDisposedException) { } } //Close the input stream if it is not closed. if (_inputStream.IsOpen) { try { _inputCollection.Complete(); _inputStream.Close(); } catch (ObjectDisposedException) { } } try { //Runspace object maintains a list of pipelines in execution. //Remove this pipeline from the list. This method also calls the //pipeline finished event. ((RemoteRunspace)_runspace).RemoveFromRunningPipelineList(this); PipelineFinishedEvent.Set(); } catch (ObjectDisposedException) { } }
/// <summary> /// Disposes the pipeline. /// </summary> /// <param name="disposing">True, when called on Dispose().</param> protected override void Dispose(bool disposing) { try { if (_disposed) { return; } lock (_syncRoot) { if (_disposed) { return; } _disposed = true; } if (disposing) { // wait for the pipeline to stop..this will block // if the pipeline is already stopping. Stop(); // _pipelineFinishedEvent.Close(); if (_powershell != null) { _powershell.Dispose(); _powershell = null; } _inputCollection.Dispose(); _inputStream.Dispose(); _outputCollection.Dispose(); _outputStream.Dispose(); _errorCollection.Dispose(); _errorStream.Dispose(); MethodExecutorStream.Dispose(); PipelineFinishedEvent.Dispose(); } } finally { base.Dispose(disposing); } }
/// <summary> /// Invoke the pipeline, synchronously, returning the results as an /// array of objects. /// </summary> /// <param name="input">an array of input objects to pass to the pipeline. /// Array may be empty but may not be null</param> /// <returns>An array of zero or more result objects.</returns> /// <remarks>Caller of synchronous exectute should not close /// input objectWriter. Synchronous invoke will always close the input /// objectWriter. /// /// On Synchronous Invoke if output is throttled and no one is reading from /// output pipe, Execution will block after buffer is full. /// </remarks> public override Collection <PSObject> Invoke(IEnumerable input) { // NTRAID#Windows Out Of Band Releases-915851-2005/09/13 if (_disposed) { throw PSTraceSource.NewObjectDisposedException("pipeline"); } CoreInvoke(input, true); // Wait for pipeline to finish execution PipelineFinishedEvent.WaitOne(); if (SyncInvokeCall) { // Raise the pipeline completion events. These events are set in // pipeline execution thread. However for Synchronous execution // we raise the event in the main thread. RaisePipelineStateEvents(); } if (PipelineStateInfo.State == PipelineState.Stopped) { return(new Collection <PSObject>()); } else if (PipelineStateInfo.State == PipelineState.Failed && PipelineStateInfo.Reason != null) { // If this is an error pipe for a hosting applicationand we are logging, // then log the error. if (this.Runspace.GetExecutionContext.EngineHostInterface.UI.IsTranscribing) { this.Runspace.ExecutionContext.InternalHost.UI.TranscribeResult(this.Runspace, PipelineStateInfo.Reason.Message); } throw PipelineStateInfo.Reason; } // Execution completed successfully // 2004/06/30-JonN was ReadAll() which was non-blocking return(Output.NonBlockingRead(Int32.MaxValue)); }
/// <summary> /// Stop the running pipeline. /// </summary> /// <param name="syncCall">If true pipeline is stoped synchronously /// else asynchronously.</param> private void CoreStop(bool syncCall) { // Is pipeline already in stopping state. bool alreadyStopping = false; lock (SyncRoot) { switch (PipelineState) { case PipelineState.NotStarted: SetPipelineState(PipelineState.Stopping); SetPipelineState(PipelineState.Stopped); break; // If pipeline execution has failed or completed or // stoped, return silently. case PipelineState.Stopped: case PipelineState.Completed: case PipelineState.Failed: return; // If pipeline is in Stopping state, ignore the second // stop. case PipelineState.Stopping: alreadyStopping = true; break; case PipelineState.Running: SetPipelineState(PipelineState.Stopping); break; } } // If pipeline is already in stopping state. Wait for pipeline // to finish. We do need to raise any events here as no // change of state has occurred. if (alreadyStopping) { if (syncCall) { PipelineFinishedEvent.WaitOne(); } return; } // Raise the event outside the lock RaisePipelineStateEvents(); // A pipeline can be stoped before it is started. See NotStarted // case in above switch statement. This is done to allow stoping a pipeline // in another thread before it has been started. lock (SyncRoot) { if (PipelineState == PipelineState.Stopped) { // Note:if we have reached here, Stopped state was set // in PipelineState.NotStarted case above. Only other // way Stopped can be set when this method calls // StopHelper below return; } } // Start stop operation in derived class ImplementStop(syncCall); }