繁体   English   中英

ValueTask.Preserve() 的意义何在?

[英]What is the point of ValueTask.Preserve()?

ValueTaskValueTask<TResult>有一个Preserve()方法,概括为“获取一个可以在未来任何时候使用的 ValueTask”。

那是什么意思,我们什么时候应该使用它? 这是否意味着“在未来的任何时候”都不能使用“正常”的ValueTask 如果是这样,为什么?

ValueTask是对Task的性能优化,但这种性能是有代价的:您不能像Task那样自由地使用ValueTask 文档提到了这些限制:

绝不应该在ValueTask实例上执行以下操作:

  • 多次等待实例。
  • 多次调用AsTask
  • 使用这些技术中的一种以上来使用实例。

这些限制仅适用于由ValueTask支持的IValueTaskSource ValueTask也可以由TaskTResult值(对于ValueTask<TResult> )支持。 如果您 100% 确定ValueTask不受IValueTaskSource支持,您可以像使用Task一样自由使用它。 例如,您可以await多次,或者您可以同步等待它完成.GetAwaiter().GetResult()

通常您不知道ValueTask是如何在内部实现的,即使您知道(通过研究源代码)您也可能不想依赖实现细节。 使用ValueTask.Preserve方法,您可以创建一个新的ValueTask来表示原始ValueTask ,并且可以不受限制地使用,因为它不是由IValueTaskSource烘焙的。 仅当此方法由 IValueTaskSource 支持时,它才会影响原始ValueTask ,否则它是空操作(它只返回未IValueTaskSource的原始任务)。

ValueTask preserved = originalValueTask.Preserve();

调用Preserve后,原来的ValueTask已经被消费了。 不应再等待它,或再次Preserve d,或使用AsTask方法将其转换为Task 执行任何这些操作都可能导致InvalidOperationException 但是现在你有了它的preserved表示,可以像Task一样自由使用它。


我的回答最初包括一个使用Preserve方法的实际例子,但事实证明这是不正确的。 这个例子可以在这个答案的第四次修订中找到。

文档不是很清楚。 来源

/// <summary>null if representing a successful synchronous completion, 
/// otherwise a <see cref="Task"/> or a <see cref="IValueTaskSource"/>.</summary>
internal readonly object? _obj;

ValueTask内部声明一个可为空的容器 object 以保存ValueTask封装的TaskIValueTaskSource (如果它是这样做的ValueTask )。 如果null代表完成, ValueTask

public ValueTask Preserve() => _obj == null ? this : new ValueTask(AsTask());

Preserve()ValueTask表示TaskIValueTaskSource (即: _obj != null )的情况下返回表示其基础任务的新ValueTask ,否则如果ValueTask表示成功的同步完成,则仅返回其自身。 这是必要的,因为_obj是内部的,无法在外部进行测试。

暂无
暂无

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

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