-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Expose an event corresponding to the runspace stopping #24646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is something @jborean93's PR: #24620 might be able to solve (?) |
Thanks @santisq. Somehow I missed that. It looks like there are a handful of related proposals as follows:
I'm closing this as a duplicate of #24620 and PowerShell/PowerShell-RFC#382. I hope that makes it into PowerShell. |
Yep the PR exposes a CancellationToken that is hooked up to the stop event allowing you to easily pass it through to async tasks. See the RFC (still to be approved) for some more background details around the problem and the approach the PR has taken PowerShell/PowerShell-RFC#382. Right now the only public API is overriding the StopProcessing method in a compiled cmdlet which is called when the engine is requested to stop. Unfortunately this is not available in a script function so your only option for calling and awaiting a .NET task is to not do a blocking wait on the .net call but have a small spin lock that waits for the task to complete, e.g. $task = [System.Threading.Tasks.Task]::Delay(10000)
while (-not $task.IsCompleted) { Start-Sleep -Milliseconds 300 }
$task.GetAwaiter().GetResult() |
@jborean93 If I'm understanding this correctly, there might be a way to emit a token from a compiled command (e.g. Start-Job {
CancellationContext {
param($CancellationToken)
# do all user work here
}
} Your proposal is way nicer ergonomics, but this might be an adequate stop-gap. At least the API used is public. |
Yup. This works. There is a demo here. I'd prefer the solution from the RFC, but this works even in Windows PowerShell. |
Is there a script block for Linux? $jobRunning = [System.Threading.EventWaitHandle]::new($false,'ManualReset','event_1f242755') |
@kasini3000 I’m surprised by that error message. The API catalog entry for that overload says “This API is supported on all platforms.” For the use in my OP you can use another synchronization method like checking for files or probably even sleeps. |
1 On Windows, the script block works as expected. |
The docs are somewhat unclear but I don’t believe named EventWaitHandle is supported outside of Windows. It seems like the only cross platform synchronisation primitive that is supported is a Mutex https://learn.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives#waithandle-class-and-lightweight-synchronization-types
|
@jborean93 Short of attempting to call each API on each platform, do you see a better way than apisof.net to check whether an API is supported? |
@kasini3000 I've update both the OP demo and this demo to use a primitive that I expect is more linux-friendly. But those demos now rely on thread jobs, which, I think, are still shipped as a separate module. |
The documentation on the types and methods themselves. Granted the one for |
@alx9r good,thanks! for next : |
I did my take including a timeout, last example from: https://github.com/santisq/PSUsing?tab=readme-ov-file#usage
|
@santisq Thank you for sharing. Or |
Hi @kasini3000, I'll not be doing any PR but in case you want to have a Hope it helps!
|
@santisq I'll give it a try |
Uh oh!
There was an error while loading. Please reload this page.
Summary of the new feature / enhancement
As a user of long-running .Net calls that accept
System.Threading.CancellationToken
I would like to be able to configure those calls to be canceled when I stop the PowerShell job where they are running. To accomplish that I would need some way to obtain or fashion aCancellationToken
whose cancellation corresponds to the job's runspace entering the "Stopping" state.Consider the desired use-case
which would complete quickly after calling
Stop-Job
. Contrast that with what is currently possible with public APIswhich waits the full
millisecondsDelay
before completing.Proposed technical implementation details
The above seems to be possible using reflection to subscribe to a non-public
Stopping
state transition event. A demonstration of that is shown in the code below. That demo outputswhich indicates the following:
millisecondsDelay
end{}
is never reachedclean{}
is invoked indicating graceful stopping of the runspace succeededDemo
The text was updated successfully, but these errors were encountered: