interactive
interactive copied to clipboard
`KernelInvocationContext.Current.CancellationToken` is unreliable in VS Code
Describe the bug
I've tried using KernelInvocationContext.Current.CancellationToken
to cancel long-running tasks as described here but it rarely ever works.
Please complete the following:
Which version of .NET Interactive are you using? (In a notebook, run the #!about
magic command. ):
- Version: 1.0.425803+1db2979099d0272660e1497cae9b9af1238db42f
- Library version: 1.0.0-beta.23258.3+1db2979099d0272660e1497cae9b9af1238db42f
- Build date: 2023-05-17T14:00:58.1639536Z
- OS: Windows 11
- Frontend: Visual Studio Code 1.78.2
Reproduction
#r "nuget:System.Reactive"
using System.Reactive.Linq;
using System.Threading;
using Microsoft.DotNet.Interactive;
var subscription = Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(
value => Console.WriteLine($"OnNext: {value}"),
ex => Console.WriteLine($"OnError: {ex}"),
() => Console.WriteLine("OnCompleted"));
Console.WriteLine("Subscribed");
var cts = CancellationTokenSource.CreateLinkedTokenSource(
KernelInvocationContext.Current.CancellationToken);
cts.CancelAfter(TimeSpan.FromSeconds(15)); // Prevent infinite wait due to bug
await Task.Delay(-1, cts.Token).ContinueWith(_ => { }, TaskContinuationOptions.OnlyOnCanceled);
subscription.Dispose();
Console.WriteLine("Disposed");
cts.Dispose();
Just keep running the above reproduction, clicking the "Cancel" button before 15s, and you're bound to run into the problem.
Recent improvements in #2982 might have improved this.
This seems to have been fixed (kind of). My code still doesn't get notified of the cancellation through the token, but the program is actually terminated now. Is the expectation that canceling is effectively the same as "force stop" where there is no opportunity for cleanup?
Cancellation is best effort. Any code path that's not checking the CancellationToken
will simply continue to run.
An API to actually force a stop (a kind of replacement for the .NET Framework-only Thread.Abort
) was introduced in .NET 7 and we plan to adopt it in .NET Interactive but there's some additional work needed.