The*_*ias 5 .net c# state-machine async-await
根据该文件一ValueTask<TResult>...
提供包装a
Task<TResult>和a 的值类型TResult,仅使用其中一个。
我的问题是关于async遇到关键字时C#编译器生成的状态机。是不是足够聪明,以产生ValueTask<TResult>一个包装了TResult,当结果是立即可用,或者一个一个包装了Task<TResult>,当结果来后await?这是一个例子:
static async ValueTask<DateTime> GetNowAsync(bool withDelay)
{
if (withDelay) await Task.Delay(1000);
return DateTime.Now;
}
static void Test()
{
var t1 = GetNowAsync(false);
var t2 = GetNowAsync(true);
}
Run Code Online (Sandbox Code Playgroud)
调用GetNowAsync(false)应该返回一个TResult包装器,因为没有等待任何内容,而调用GetNowAsync(true)应该返回一个Task<TResult>包装器,因为Task.Delay在结果变为可用之前已经等待了a 。我担心状态机总是返回Task包装器,从而使ValueTask类型的所有优点都无效Task(并保留所有缺点)的可能性。据我所知,该类型的属性ValueTask<TResult>未提供有关其内部包装内容的指示。我将上面的代码粘贴到sharplab.io,但是输出也没有帮助我回答这个问题。
我想我应该回答我自己的问题,因为我现在知道答案了。答案是我的担心是没有根据的:C# 编译器足够聪明,可以在每种情况下发出正确的类型ValueTask<TResult>。当结果同步可用时,它会发出一个值包装器;当结果不同步时,它会发出一个任务包装器。
我通过性能测量得出了这个结论:通过测量每种情况下分配的内存以及创建相同数量的任务所需的时间。结果清晰且一致。例如, aValueTask<int>在包装一个int值时正好消耗 12 个字节,而在包装 a 时正好消耗 48 个字节Task<int>,因此毫无疑问其幕后发生了什么。
| 归档时间: |
|
| 查看次数: |
126 次 |
| 最近记录: |