Skip to content

[API Proposal]: CancellationToken.OnReset event #81255

@timcassell

Description

@timcassell

Background and motivation

I maintain a custom cancelation token that can be converted to and from System.Threading.CancellationToken. Since the CancellationTokenSource.TryReset API was introduced in .Net 6, I have had to do some heavy-handed work to re-register my token to keep listening for the cancelation. Being able to listen to an event for when the source is reset would allow me to only re-register at that time, and remove a lot of code.

API Proposal

namespace System.Threading;

public struct CancellationToken
{
    public event Action OnReset;
}

API Usage

public class MyCustomToken
{
    public class MyCustomToken(CancellationToken token)
    {
        token.OnReset += () => token.Register(OnCanceled);
        token.Register(OnCanceled);
    }
    
    private void OnCanceled()
    {
        // Logic for custom cancelation,
        // including handling the case of double registration due to a thread race.
    }
    
    // Other public methods that are irrelevant for this proposal...
}

Alternative Designs

#60843 Was an idea to have an alternative callback when the callback is unregistered without being invoked, but it wasn't good because it would increase the cost of other more common operations. This proposal deals with that issue by only raising a global event when TryReset is called, instead of individual callbacks for each registration, so other operations aren't affected (and memory increase for the event is minimal).

Risks

Slightly increases memory of CancellationTokenSource.

Possible race condition if TryReset is called on another thread while registering the first time (but that would be a mis-use of the TryReset API, going against the intended use laid out in the documentation, and that's already a possible race condition today).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions