首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ValueTask<TResult>和异步状态机

ValueTask<TResult>和异步状态机
EN

Stack Overflow用户
提问于 2019-08-10 06:56:55
回答 2查看 925关注 0票数 7

根据文档 a ValueTask<TResult>..。

提供一个值类型,该值类型包装Task<TResult>TResult,仅使用其中一种。

我的问题是C#编译器在遇到async关键字时生成的状态机。当结果立即可用时,生成一个包装一个TResultTResult,还是在一个await之后生成一个包装Task<TResult>await,这是否足够明智?下面是一个示例:

代码语言:javascript
复制
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);
}

调用GetNowAsync(false)应该返回一个TResult包装器,因为没有等待,调用GetNowAsync(true)应该返回一个Task<TResult>包装器,因为在结果可用之前等待一个Task.Delay。我担心状态机总是返回Task包装器,否定了ValueTask类型相对于Task的所有优点(并保留了所有的缺点)。据我所知,ValueTask<TResult>类型的属性没有说明它在内部包装了什么。我将上面的代码粘贴到sharplab.io,但是输出也没有帮助我回答这个问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-08-23 16:15:29

我想我应该回答我自己的问题,因为我现在知道答案了。答案是,我的担忧是没有道理的:-- C#编译器非常聪明,在每种情况下都能发出正确的ValueTask<TResult>类型。当结果同步可用时,它会发出一个值包装器,而如果不是,则会发出一个任务包装器。

我通过性能度量得出了这个结论:通过测量在每种情况下分配的内存,以及创建相同数量的任务所需的时间。结果是明确和一致的。例如,当一个ValueTask<int>包装一个int值时,它要消耗整整12个字节,当它包装一个Task<int>时,它要消耗精确的48个字节,所以毫无疑问,它下面发生了什么事情。

票数 3
EN

Stack Overflow用户

发布于 2019-08-10 15:36:57

编译器蠢到可以做它被告知的事情:

https://source.dot.net/#System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs,409

代码语言:javascript
复制
[AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))]
[StructLayout(LayoutKind.Auto)]
public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>

小心使用ValueTask

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57440047

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档