V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jmliubiao
V2EX  ›  C#

C#中异步相关的问题

  •  
  •   jmliubiao · 1 天前 · 312 次点击
    get1 和 get2 接口的区别是一个加了 async 、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  
       1 天前
    以前整理的 https://netnr.com/184

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

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

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

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

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

    Task<T> M();

    那么

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

    没什么区别,当然 TestController 里面 Get1Async, Get2Async 因为调用了 TsetService 里面不同的方法,实际的效果区别很大。
    csys
        5
    csys  
       1 天前
    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#生成一个异步状态机,从而轻微避免了一些性能负担

    我的经验里,这种场景非常少,实际上,一个方法的所有职责仅仅是为了调用另一个方法,本身就是一种代码坏味道
    jmliubiao
        6
    jmliubiao  
    OP
       1 天前
    @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
       1 天前
    @csys 是的,一个方法的所有职责仅仅是为了调用另一个方法的观点我认同。但现实的项目有不少这样的代码。有的有加 async 、await 返回,有的又没加。
    geelaw
        8
    geelaw  
       1 天前
    @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  
       1 天前
    这个例子问题其实不大。

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

    asp.net 请求结束后,对象会被释放。
    如果异步操作还没跑完,可能会引发 ObjectDisposedException 异常。
    而且这么写,数据库操作这块出错,也可能抓取不到异常。
    seleningchan1
        10
    seleningchan1  
       1 天前
    还有 C#的岗位吗
    jmliubiao
        11
    jmliubiao  
    OP
       1 天前
    @seleningchan1 上位机还是有的。
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2115 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 04:27 · PVG 12:27 · LAX 21:27 · JFK 00:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.