如果一个API返回ValueTask
或ValueTask<T>
,是否有方法对其执行ContinueWith
,就像我可以使用Task
做的那样?是否有适用于.NET Standard 2.0的微软提供的NuGet库来实现这一点?
如果一个API返回ValueTask
或ValueTask<T>
,是否有方法对其执行ContinueWith
,就像我可以使用Task
做的那样?是否有适用于.NET Standard 2.0的微软提供的NuGet库来实现这一点?
valueTask.AsTask()
。 AsTask()
是为像您这样的用例而设计的逃生口,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);
}
await
之前 Preserve
ValueTask<TResult>
,然后使用保留的任务作为参数调用 continuationAction
。即使任务成功完成,这样做也会导致内存分配。Task.FromCanceled
方法的原因是,该方法要求提供的 CancellationToken
已被取消,否则将抛出 ArgumentOutOfRangeException
异常。我知道我发帖晚了,但是我还是想分享一下我采用的方法...
ValueTask<T> vt = ValueTaskTReturningMethod();
var awt = vt.GetAwaiter();
awt.OnCompleted(() => {
T val = awt.GetResult();
//code you want to execute after async operation completes
}
T val = await vt; // 你想要执行的代码...
- 更简单。 - Marc Gravell
ContinueWith
是遗留的 API。坦白地说,你根本不应该使用它。你应该同时使用await
和value-task
。 - Marc Gravell