C#中异步相关的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jmliubiao
V2EX    C#

C#中异步相关的问题

  •  
  •   jmliubiao 10 天前 530 次点击
    get1 和 get2 接口的区别是一个加了 asnc 、await 一个没加的区别,加了 async 、await 会额外生成一些状态机相关的代码,除了这个区别还有其他区别吗?
    我的理解是,如果不需要获取异步后的结果进行其他处理则可以不用加。如果不加 async 、await ,真到生产上会不会有什么问题?

    示例代码:
    using Microsoft.AspNetCore.Mvc;

    namespace WebApplication1.Controllers
    {
    [ApiController]
    [Route("api/[controller]")]
    public class TestController : ControllerBase
    {
    [HttpGet("get1")]
    public Task<Student> Get1Async()
    {
    return new TsetService().Get1Async();
    }
    [HttpGet("get2")]
    public async Task<Student> Get2Async()
    {
    return await new TsetService().Get2Async();

    }
    }


    public class TsetService
    {

    public Task<Student> Get1Async()
    {
    // 模拟数据库查询
    Task.Delay(100);
    return Task.FromResult(new Student { Id = 1, Name = "张三" });
    }

    public async Task<Student> Get2Async()
    {
    // 模拟数据库查询
    await Task.Delay(100);
    return new Student { Id = 1, Name = "张三" };
    }
    }

    public class Student
    {
    public int Id { get; set; }
    public string Name { get; set; }
    }
    }
    11 条回复    2025-09-30 09:30:28 +08:00
    netnr
        1
    netnr  
       10 天前
    以前整理的 https://netnr.com/184

    数据库查询,简单的说,不能提升单个请求性能,但能提升并发请求处理,QPS 提升
    jmliubiao
        2
    jmliubiao  
    OP
       10 天前
    @netnr 你说的这些我都清楚,但是没有找到我想问的答案
    geelaw
        3
    geelaw  
       10 天前
    楼主应该善待帮助自己的人,比如提供格式化之后的代码。

    TestController 里面的代码没什么意思上的差别,Get1Async 没有额外包装,或许性能会好一些。

    TsetService (维持楼主的错误拼写)里面则完全不同。

    Get1Async 完全抛弃了 Task.Delay(100),所以 Get1Async 实际上没有任何延迟,return Task.FromResult 是同步执行的,await Get1Async() 也不会有延迟,因为被 await 对象是已经完成的 Task.FromResult 。

    await Get2Async() 有 100ms 延迟。
    geelaw
        4
    geelaw  
       10 天前
    @geelaw #3 所谓没有意思上的差别,是指假设有

    Task<T> M();

    那么

    Task<T> M1() { return M(); }
    async Task<T> M2() { return await M(); }

    没什么区别,当然 TestController 里面 Get1Async, Get2Async 因为调用了 TsetService 里面不同的方法,实际的效果区别很大。
    csys
        5
    csys  
       10 天前
    https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/master/AsyncGuidance.md?utm_source=csharpdigest&utm_medium&utm_campaign=286#prefer-asyncawait-over-directly-returning-task

    简单来说,如果你的整个方法内部没有任何别的事情要做,就是单独一个 Task ,那么你直接 return 而非 await 这个 task ,可以避免 C#生成一个异步状态机,从而轻微避免了一些性能负担
    br />我的经验里,这种场景非常少,实际上,一个方法的所有职责仅仅是为了调用另一个方法,本身就是一种代码坏味道
    jmliubiao
        6
    jmliubiao  
    OP
       10 天前
    @geelaw 感谢你的回复,格式的问题不知道为什么发布后就变成这样了。
    TsetService 里的方法我想表达是一个查询数据的动作。 类似这样:reutrn db.Set<Student>().FindAsync(x => x.Id == 1) 和 reutrn await db.Set<Student>().FindAsync(x => x.Id == 1) 。
    jmliubiao
        7
    jmliubiao  
    OP
       10 天前
    @csys 是的,一个方法的所有职责仅仅是为了调用另一个方法的观点我认同。但现实的项目有不少这样的代码。有的有加 async 、await 返回,有的又没加。
    geelaw
        8
    geelaw  
       10 天前
    @jmliubiao #6 oh wow 你应该看 #5 的信息,我记错了……

    TestController 代码的效果只有无异常的情况下是一样的,考虑 new TsetService() 这个表达式产生异常的情况(比如内存不足,或者构造器抛出异常),那么 Get1Async 会同步得到异常,而 Get2Async 会把异常装进 Task<Student> 里面返回。

    Task<int> M1(bool t) { if (t) throw new Exception(); return Task.FromResult(0); }
    async Task<int> M2(bool t) { if (t) throw new Exception(); return 1; }

    那么

    try { M1(); } catch(Exception ex) { Console.WriteLine("caught M1"); }
    M2(); Console.WriteLine("M2 succeeded");

    的结果是

    caught M1
    M2 succeeded

    因为 M2 的异常只有在 await 的时候才会浮现。但是 #5 说由于这个(异常总是异步的)优点所以应该尽量用 async/await 我就不知道了,我的感觉是最终使用的时候所有 Task 都要被 await ,此时包围之的方法必然是 async ,因此同步异常和异步异常最后都会浮现,时机不同,而且典型的代码里还会掺杂很多其他可能异常的语句,就看细抠异常语义是否有意义吧。
    i8086
        9
    i8086  
       10 天前
    这个例子问题其实不大。

    如果 Get1Async() 方法 Task.Delay(100) 被替换为一组耗时的数据库操作。

    asp.net 请求结束后,对象会被释放。
    如果异步操作还没跑完,可能会引发 ObjectDisposedException 异常。
    而且这么写,数据库操作这块出错,也可能抓取不到异常。
    seleningchan1
        10
    seleningchan1  
       10 天前
    还有 C#的岗位吗
    jmliubiao
        11
    jmliubiao  
    OP
       9 天前
    @seleningchan1 上位机还是有的。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     863 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 22ms UTC 21:22 PVG 05:22 LAX 14:22 JFK 17:22
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86