这里提出的问题与一张在这里相同,目的是为它创造一个明确的解决方案。最准确的答案是Stephen自己在本期中,这正是关于这个问题的。“推荐的代码”如下:
public static ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
{
if (valueTask.IsCompletedSuccessfully)
{
valueTask.GetResult();
return default;
}
return new ValueTask(valueTask.AsTask());
}这个答案并不是最新的-- ValueTask不公开一个GetResult() (只是一个结果属性)--问题是:
.GetAwaiter()调用吗?var fake = valueTask.Result;的工作?一直都是?(我害怕死代码消除。)
public static ValueTask AsNonGenericValueTask<T>( in this ValueTask<T> valueTask )
{
return valueTask.IsCompletedSuccessfully ? default : new ValueTask( valueTask.AsTask() );
}发布于 2020-04-16 21:06:11
代码中缺少的是.GetAwaiter()
public static ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
{
if (valueTask.IsCompletedSuccessfully)
{
valueTask.GetAwaiter().GetResult();
return default;
}
return new ValueTask(valueTask.AsTask());
}你在一定程度上是对的,因为你不在乎结果。但是您可能关心抛出的异常或取消,如果您不查询结果,就会错过这些异常或取消。
或者你可以这样写:
public static async ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
=> await valueTask;发布于 2022-03-28 01:27:01
您可以使用以下两种方法:
valueTask.GetAwaiter().GetResult();...or:
_ = valueTask.Result;这两种委托都是底层IValueTaskSource.GetResult方法的,假设ValueTask<T>是由IValueTaskSource支持的。使用更短(第二)的方法应该会稍微更有效率,因为它只需要少调用一次方法。
你也可以完全忽略这个结果。不需要至少等待一次ValueTask<T>,或者至少检索一次其结果。这是完全有效的,得到一个ValueTask<T>,然后忘记它。有记录的限制是:
ValueTask<TResult>实例只能等待一次,..。
这是“只可能”,而不是“必须”。
不过,取得这个结果仍然是个好主意。通过检索结果,您将发出ValueTask<TResult>已被消耗的信号,因此可以重用底层的IValueTaskSource<T>。重用IValueTaskSource<T>实例可以提高ValueTask<T>-based实现的效率,因为它们分配内存的频率较低。为了获得一个想法,请看一下内部的System.Threading.Channels.AsyncOperation类。该类实现IValueTaskSource<TResult>接口。下面是如何实现GetResult:
/// <summary>Gets the result of the operation.</summary>
/// <param name="token">The token that must match <see cref="_currentId"/>.</param>
public TResult GetResult(short token)
{
if (_currentId != token)
{
ThrowIncorrectCurrentIdException();
}
if (!IsCompleted)
{
ThrowIncompleteOperationException();
}
ExceptionDispatchInfo? error = _error;
TResult? result = _result;
_currentId++;
if (_pooled)
{
Volatile.Write(ref _continuation, s_availableSentinel); // only after fetching all needed data
}
error?.Throw();
return result!;
}将私有字段Action<object> _continuation设置为静态只读值s_availableSentinel允许后续异步操作重用AsyncOperation<TResult> (例如,ChannelReader.ReadAsync )。否则,下一个异步操作将分配一个新的AsyncOperation<TResult>实例。
https://stackoverflow.com/questions/61256813
复制相似问题