-
Notifications
You must be signed in to change notification settings - Fork 4.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Then
or ContinueWithResult
extension method for Task
#58692
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
There is already such method . |
@omariom that is not the method that this issue describes. I nearly always end up writing an extension method to do this, which cause I'm an FP nerd I always call bind because this is monadic bind. It's useful, gives the same semantics as await pretty much but in a method calling/function passing style rather than a sequential code/keyword style. |
Why? Your example: // Read all text from file asynchronously
File.ReadAllTextAsync(filepath)
.Then(text => {
// Use the file text
Console.WriteLine(text);
return text.Length;
}); becomes: string text = await File.ReadAllTextAsync(filepath);
Console.WriteLine(text);
return text.Length; Such |
@gulshan this seems resolved, do you want to close? |
I would still like to have this extension method available in standard library, if not now, maybe sometime in future. But it is your decision to make at the end. |
@stephentoub solving this problem with async/await is not 100% satisfying, because it results to all but the first exceptions stored inside the task to get swallowed. Having to attach continuations to |
That is the nature of async/await. And even if these helpers flowed multiple exceptions through to the returned Task, the 99.9% case of consuming the resulting Task will itself be with await, at which point the effort to flow the additional exceptions is for naught. I understand your point, but I don't personally see this as sufficient motivation; wanting such Then methods instead of await is already niche, and then wanting them because of a desire to flow multiple exceptions is a niche corner of niche ;-) |
@stephentoub this is my best attempt to implement a public static Task<TNewResult> Then<TResult, TNewResult>(
this Task<TResult> source,
Func<TResult, TNewResult> continuationFunction,
CancellationToken cancellationToken = default,
TaskContinuationOptions continuationOptions = TaskContinuationOptions.None,
TaskScheduler scheduler = null)
{
scheduler ??= TaskScheduler.Current;
return source.ContinueWith(t =>
{
if (t.IsCanceled) t.GetAwaiter().GetResult(); // Propagate the correct token
if (t.IsFaulted)
{
var tcs = new TaskCompletionSource<TNewResult>();
tcs.SetException(t.Exception.InnerExceptions);
return tcs.Task;
}
var newResult = continuationFunction(t.Result);
return Task.FromResult(newResult);
}, cancellationToken, continuationOptions, scheduler).Unwrap();
} |
I think that's more complicated than it needs to be: source.ContinueWith(t => t.IsCompletedSuccessfully ? Task.FromResult(continuationFunction(t.Result)) : t,
cancellationToken, continuationOptions, scheduler ?? TaskScheduler.Current).Unwrap(); |
Then
or ContinueWithResult
extension method for resultThen
or ContinueWithResult
extension method for Task
This gives this error on the ternary operator:
It's a pain when the continuation has different result type than the source task. |
Ah, I missed that you were trying to change the result type. Then what you have looks like a reasonable implementation to maintain multiple exceptions for whatever library you're using this in. |
I'm going to close this. While I appreciate the desire for such methods and your submitting a proposal, |
Background and motivation
Task
currently has a method group namedContinueWith
, which supports doing something when the task is finished and result is available or there is an exception. But it takes the mainTask
as a parameter and successful completion of theTask
has to be checked andResult
has to be accessed manually.The proposal is to give a new extension method for
Task
andTask<T>
, which will called with the result of the Task, only if the task has been completed successfully. The name of the method can beThen
orContinueWithResult
. It will return a task combining the given task and the continuation. If the continuation is also a task, this will merge them into a new task and return.With
Then
, the method chaining will become easier, which is a bit difficult withawait
and quite cumbersome with currentContinueWith
method.API Proposal
API Usage
Risks
No response
The text was updated successfully, but these errors were encountered: