My application has two distinct states, each of them having independent set of resources, but only one of them can be active at a time.

The state is represented by a class which holds managed references to various services. For simplicity let's just assume this:

```cs
class FirstApplicationState {
  ServiceA FooService { get; }
  ServiceB BarService { get; }
}

// Some 'global' object holds reference to State
Application.State = new FirstApplicationState();

```

The `ServiceA` class during execution launches a delayed-execution task.

```cs
class ServiceA {
  CancellationTokenSource tsc;

  private async Task TriggerDelayedActionAsync() {
    try {
       tsc = new CancellationTokenSource();
       await Task.Delay(TimeSpan.FromMinutes(1),tsc.Token);
    }
    catch(TaskCancelledException) {
      Log.Info("Task cancelled");
      return;
    }
    finally { /*dispose tsc*/ }

    await RunVeryLongTaskAsync();
  }
}

```

The task should no longer execute if the `FirstApplicationState` is no longer the active state of the application. If the state will go out of scope and the entire hierarchy will be marked to be colleced by invoking `Application.State = null` while the `Task.Delay()` method is being awaited, the instance of `ServiceA` won't be marked for GC collection, and the await will finally execute, invoking the `RunVeryLongTaskAsync` method, which will load some resources and potentially throw an exception.

To avoid it, the natural solution would be to just introduce some `Deinitialize()` method to services and run a deinitialization process which will properly trigger all cancellation tokens before the Application allows for marking state for GC collection, although it seems like requiring tracking cancellation tokens for all potential tasks.

I'm wondering if there is some other mechanism, which would let me cancel all tasks once object executing them goes out of scope? While not relying on it for proper state cleanup, maybe I can check if any tasks on entire hierarchy of objects are still running for debugging purposes? I'm also considering using double-source cancellation tokens which would allow me for some higher level cancellation like described [in Microsoft's docs](https://learn.microsoft.com/en-us/dotnet/standard/threading/how-to-listen-for-multiple-cancellation-requests), but I'm not sure how common of a practice is this as I haven't encountered similar solutions before.