interactive icon indicating copy to clipboard operation
interactive copied to clipboard

`KernelInvocationContext.Current.CancellationToken` is unreliable in VS Code

Open gtbuchanan opened this issue 1 year ago • 3 comments

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.

gtbuchanan avatar May 17 '23 17:05 gtbuchanan

Recent improvements in #2982 might have improved this.

jonsequitur avatar Jun 08 '23 16:06 jonsequitur

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?

gtbuchanan avatar Oct 18 '23 16:10 gtbuchanan

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.

jonsequitur avatar Dec 16 '23 18:12 jonsequitur