[API Proposal]: ValueTask->Task: allow deferred callback hook for IVTS scenario

Open
#119,232 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Stale
Tech stack
csharp
Domain
tooling

Research direction

Start with the linked ValueTask.cs code around the custom Task subscription for typed and untyped IVTS cases. Trace how status checks and completion operations currently subscribe, then define the deferred-state behavior for the two proposed usage scenarios. Done means the subscription is deferred until a result-related operation and the pending and fault-detected paths are covered by tests.

Written by the indexing model from the issue text.

Description

api-suggestion area-System.Threading.Tasks needs-further-triage
Background and motivation

There are times when awaitable items are used as "futures", but in a pre-pending state. Meaning: trying to await them right now will be a doomed deadlock, unless you have some kind of cancellation/timeout in place. Example:

// SE.Redis
var tran = dB.CreateTransaction();
var pending = tran.IncrAsync(key);
//... others
await pending; // ERROR
// the above is doomed until after
await tran.ExecuteAsync();

// down here (after the ExecuteAsync): this would be fine
var count = await pending;

This is detectable in custom awaitables, and in valuetasks based on IVTS - we can check the state in OnCompleted etc, and if it is doomed: transition into a faulted state. However, this currently doesn't work if someone has used AsTask() to get the pending operation as a Task, because the custom Task for IVTS subscribes immediately, here (x2, typed/untyped). This means that the moment they call AsTask, we would transition it to doomed.

API Proposal

No public API change.

Internally, use a deferred subscription mechanism for Pending IVTS cases. The IVTS is already stored (otherwise, we could use AsyncState). Proposal: add a new deferred state; when in that state:

  • status checks (IsCompleted, etc) should refer to the IVTS instead of locally
  • result related operations (Wait, GetResult, OnCompleted, ContinueWith, etc) would only then, first time subscribe to the IVTS via OnCompleted etc, transitioning back into local mode; once in local mode, normal service is resumed
API Usage

No public signature change. Behaviourally, the following scenario becomes possible:

var task = prePendingIVTS.AsTask();
MakeHappy(prePendingIVTS); //
await task; // fine

And

var task = prePendingIVTS.AsTask();
await task; // boom, fault detected

The point here is correctness and simplicity of debugging. Currently, because we can't prevent people turning VTs to Ts via AsTask(), we have to omit the deadlock detection that would have told them what they did wrong.

Probably a @stephentoub topic!

I can provide examples and tests if this is of interest.

Alternative Designs
Risks

No response

Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/runtime

All issues in dotnet/runtime

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.