Add a `PipelineStopToken` cancellation token property to `PSCmdlet`
Summary of the new feature / enhancement
A common pattern for binary cmdlets is to create a cancellation token source that is then cancelled in PSCmdlet.StopProcessing().
This is a very useful pattern to enable cancelling a method that takes CancellationToken without having to poll for completion. Having this available by default would reduce a lot of boilerplate in binary cmdlets. Boilerplate example:
namespace MyModule;
[Cmdlet(VerbsDiagnostic.Test, "MyCommand")]
public class TestMyCommand : PSCmdlet, IDisposable
{
private readonly CancellationTokenSource _stopping = new();
protected override void ProcessRecord()
{
try
{
Task.Delay(2000, _stopping.Token).GetAwaiter().GetResult();
}
catch (OperationCancelledException)
{
throw new PipelineStoppedException();
}
}
protected override void StopProcessing() => _stopping.Cancel();
public void Dispose() => _stopping.Dispose();
}
This pattern is not possible in PowerShell directly, instead a script must poll a task for completion if it wants to respect pipeline stops. Polling example:
$task = [System.Threading.Tasks.Task]::Delay(2000)
while (-not $task.AsyncWaitHandle.WaitOne(200)) { }
$null = $task.GetAwaiter().GetResult();
Even then all you can do is honor pipeline stops, you can't request cancellation of the work being done in another thread.
Proposed technical implementation details (optional)
namespace System.Management.Automation;
public abstract class PSCmdlet
{
+ private CancellationTokenSource? _pipelineStopTokenSource;
+ public CancellationToken PipelineStopToken => (_pipelineStopTokenSource ??= new()).Token;
protected virtual void StopProcessing()
{
using (PSTransactionManager.GetEngineProtectionScope())
{
+ _pipelineStopTokenSource?.Cancel();
}
}
internal void InternalDispose(bool isDisposing)
{
_myInvocation = null;
_state = null;
_commandInfo = null;
_context = null;
+ _pipelineStopTokenSource?.Dispose();
+ _pipelineStopTokenSource = null;
}
}
The engine WG discussed this and agrees that it would be useful. An RFC would be required as we could not unanimously agree to the proposal above.
If it is for binary cmdlets only, the public CancellationToken PipelineStopToken should be not public but protected?
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.
This issue has not had any activity in 6 months, if there is no further activity in 7 days, the issue will be closed automatically.
Activity in this case refers only to comments on the issue. If the issue is closed and you are the author, you can re-open the issue using the button below. Please add more information to be considered during retriage. If you are not the author but the issue is impacting you after it has been closed, please submit a new issue with updated details and a link to this issue and the original.