我是否需要查询我选择不等待的 ValueTask 的 .Result 属性?

Do I need to query the .Result property of a ValueTask that I choose to not await?

假设我有一个 returns 类型 ValueTask 对象的方法,例如 ChannelReader 上的 WaitToReadAsync 方法。我可以通过三种方式使用此 ValueTask。我可以:

  1. 直接等待
  2. 把它变成一个任务,然后等待它(.AsTask()
  3. 查询.Result 属性是否同步完成(如果.IsCompletedtrue)。

关于第三种方法(在 ValueTask 上调用 .Result),MSDN documentation 声明此 属性 只能查询一次。但是,这个 属性 有必要查询吗?换句话说,从不查询 ValueTask?

的结果可以吗?

这是我的意思的一个例子:

var channel = Channel.CreateUnbounded<int>();
var waitToReadValueTask = channel.Reader.WaitToReadAsync(default);
if (waitToReadValueTask.IsCompleted)
{
   if (channel.Reader.TryRead(out var result))
   {
      // Do something with the result object.
   }
}

在此示例中,waitToReadValueTask 从未被消费过。它从未被等待过,.Result 属性 也没有被调用过。这样可以吗?

好问题。是的,如果您对结果或可能存储的 Exception 不感兴趣,则完全可以省略查询 ValueTask<T>Result 属性任务里面。如果您愿意,也可以在 ValueTask 创建后完全忽略它,从而导致 so-called fire-and-forget 任务。任务仍然会完成,即使您没有保留它的任何引用。

一般来说,消费你的 ValueTask 是个好主意,可以通过 awaiting 或 AsTasking 或查询他们的 Result (前提是它们已经完成)。通过使用 ValueTask,您向底层实现发出信号,表明支持 IValueTaskSource<T> 实例可以重用。当异步方法无法同步完成时,重用 IValueTaskSource<T> 个实例是基于 ValueTask 的 API 避免内存分配的方式。

在您的示例中,您在创建 ValueTask 后立即查询 IsCompleted 属性,因此 ValueTask 在创建时未完成的可能性很小。因此,对于您的示例,上述建议仅具有理论价值。在创建时完成的 ValueTask 不受 IValueTaskSource<T> 实例的支持,因此在您的示例中不查询 Result 不会对性能产生影响。如果您在创建 ValueTask.

后稍后查询 IsCompleted 属性,该建议将具有实用价值