ValueTask
并且ValueTask<TResult>
有一个Preserve()
方法被概括为“获取一个可以在未来任何时候使用的 ValueTask”。
这是什么意思,我们应该什么时候使用它?这是否意味着ValueTask
“在未来的任何时候”都不能使用“正常”?如果是这样,为什么?
ValueTask
并且ValueTask<TResult>
有一个Preserve()
方法被概括为“获取一个可以在未来任何时候使用的 ValueTask”。
这是什么意思,我们应该什么时候使用它?这是否意味着ValueTask
“在未来的任何时候”都不能使用“正常”?如果是这样,为什么?
是对ValueTask
a 的性能优化Task
,但这种性能是有代价的:你不能像 aValueTask
那样自由地使用 a Task
。该文档提到了这些限制:
永远不应在
ValueTask
实例上执行以下操作:
- 多次等待实例。
AsTask
多次调用。- 使用这些技术中的一种以上来使用实例。
这些限制仅适用于ValueTask
由 a 支持的 s IValueTaskSource
。AValueTask
也可以由 aTask
或TResult
值(对于 a ValueTask<TResult>
)支持。如果您 100% 确定 aValueTask
不受 a 支持IValueTaskSource
,您可以像 a 一样自由使用它Task
。例如你可以await
是多次,或者你可以等待它同步完成.GetAwaiter().GetResult()
。
一般来说,您不知道 aValueTask
是如何在内部实现的,即使您知道(通过研究源代码)您也可能不想依赖实现细节。使用该ValueTask.Preserve
方法,您可以创建一个新ValueTask
的代表原始的ValueTask
,并且可以不受限制地使用,因为它不是由IValueTaskSource
. 此方法ValueTask
仅在由 支持时才会影响IValueTaskSource
原始任务,否则它是无操作的(它只是返回未更改的原始任务)。
ValueTask preserved = originalValueTask.Preserve();
调用后Preserve
,原ValueTask
已消耗。它不应再被等待,或再次 d,或使用该方法Preserve
转换为。执行这些操作中的任何一个都可能导致. 但是现在你有了它的表示,它可以像.Task
AsTask
InvalidOperationException
preserved
Task
我的回答最初包括一个使用该Preserve
方法的实际示例,但事实证明这是不正确的。这个例子可以在这个答案的第 4 版中找到。
文档不是很清楚。从来源:
/// <summary>null if representing a successful synchronous completion,
/// otherwise a <see cref="Task"/> or a <see cref="IValueTaskSource"/>.</summary>
internal readonly object? _obj;
ValueTask
内部声明一个可以为空的容器对象来保存或者Task
封装应该是一个IValueTaskSource
这样做的。否则,如果相反表示完成。ValueTask
ValueTask
null
ValueTask
public ValueTask Preserve() => _obj == null ? this : new ValueTask(AsTask());
Preserve()
如果表示 a或 an (即:) ,则返回一个新的ValueTask
表示其基础任务,否则如果表示成功同步完成,则返回自身。这是必要的,因为它是内部的,无法在外部进行测试。ValueTask
Task
IValueTaskSource
_obj != null
ValueTask
_obj