简体   繁体   English

ValueTask 有 ContinueWith 吗?

[英]Is there a ContinueWith for ValueTask?

If an API returns a ValueTask or ValueTask<T> , is there a way to perform a ContinueWith on it, like I'm able to do with Task ?如果 API 返回ValueTaskValueTask<T> ,有没有办法对其执行ContinueWith ,就像我可以使用Task一样? Is there a Microsoft-provided NuGet library for doing so with .NET Standard 2.0?是否有 Microsoft 提供的 NuGet 库与 .NET 标准 2.0 一起使用?

Use valueTask.AsTask() .使用valueTask.AsTask() AsTask() is an escape hatch for just such use cases as yours. AsTask()是像您这样的用例的逃生舱。 The purpose of ValueTask is to avoid allocations whenever possible, but if you're going to invoke a continuation on another thread, you will need to allocate something and it might as well be a Task<T> . ValueTask的目的是尽可能避免分配,但如果您要在另一个线程上调用延续,您将需要分配一些东西,它也可能是一个Task<T>

Here you are:给你:

public static async ValueTask ContinueWith<TResult>(this ValueTask<TResult> source,
    Action<ValueTask<TResult>> continuationAction)
{
    // The source task is consumed after the await, and cannot be used further.
    ValueTask<TResult> completed;
    try
    {
        completed = new(await source.ConfigureAwait(false));
    }
    catch (OperationCanceledException oce)
    {
        var tcs = new TaskCompletionSource<TResult>();
        tcs.SetCanceled(oce.CancellationToken);
        completed = new(tcs.Task);
    }
    catch (Exception ex)
    {
        completed = new(Task.FromException<TResult>(ex));
    }
    continuationAction(completed);
}

A simpler implementation would be to Preserve the ValueTask<TResult> before the await , and then invoke the continuationAction passing the preserved task as argument.一个更简单的实现是在await之前Preserve ValueTask<TResult> ,然后调用continuationAction将保留的任务作为参数传递。 This would cause invariably an allocation though, even in the case of the successful completion of the task.即使在成功完成任务的情况下,这也总是会导致分配。

The reason that I am avoiding the one-line Task.FromCanceled method in the cancellation case, is because this method requires that the supplied CancellationToken is canceled, otherwise it throws an ArgumentOutOfRangeException .我在取消情况下避免使用单行Task.FromCanceled方法的原因是因为此方法要求取消提供的CancellationToken ,否则会引发ArgumentOutOfRangeException

I know I am posting it too late.我知道我发布它为时已晚。 However wanted to share the approach I used...但是想分享我使用的方法......

ValueTask<T> vt = ValueTaskTReturningMethod();
var awt = vt.GetAwaiter();
awt.OnCompleted(() => {
   T val = awt.GetResult();
   //code you want to execute after async operation completes
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM