ValueTask.Preserve() 的意义是什么?

Pet*_*ion 4 c# async-await valuetask

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

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

The*_*ias 5

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

切勿在ValueTask实例上执行以下操作:

  • 多次等待实例。
  • AsTask多次拨打。
  • 使用其中一种以上技术来使用实例。

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

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

ValueTask preserved = originalValueTask.Preserve();
Run Code Online (Sandbox Code Playgroud)

调用后Preserve,原来的ValueTask已经被消耗掉了。它不应该再等待,或者再次 d,或者使用该方法Preserve转换。执行任何这些操作都可能会导致. 但现在您有了它的表示形式,可以像.TaskAsTaskInvalidOperationExceptionpreservedTask


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