首页 新闻 会员 周边 捐助

亲测:await和async异步编程并不能提升速度

0
悬赏园豆:20 [待解决问题]

public class UnitTest1
{

    public async Task TestMethod1Async()
    {
        Console.WriteLine($"--------------执行同步测试------------------");            
        Stopwatch watch = new Stopwatch();
        watch.Start();//开始监视代码运行时间
                      //测试代码

        var method1Result = method1();
        Console.WriteLine($"主线程执行同步method1的返回值:{method1Result}");
        var method2Result = method2();
        Console.WriteLine($"主线程执行同步method2返回值:{method2Result}");

      watch.Stop();//停止监视
      var elapsed = watch.Elapsed;//获取当前实例测量得出的总运行时间。
     var seconds = elapsed.TotalSeconds;  //  总秒数
     var milliseconds = elapsed.TotalMilliseconds;  //  总毫秒数
     Console.WriteLine($"同步结束,总耗时:{milliseconds}");


   
     Console.WriteLine($"--------------执行异步测试,当前线程id:{Thread.GetCurrentProcessorId()}--------------");
        watch = new Stopwatch();
        watch.Start();//开始监视代码运行时间

        var method1AsyncResult = await method1Async();
        Console.WriteLine($"主线程执行异步method1Async的返回值:{ method1AsyncResult},当前线程id:{Thread.GetCurrentProcessorId()}");
   
        var result2AsyncResult = await method2Async();
        Console.WriteLine($"主线程执行异步method2Async返回值:{result2AsyncResult},当前线程id:{Thread.GetCurrentProcessorId()}");

        watch.Stop();//停止监视
        elapsed = watch.Elapsed;//获取当前实例测量得出的总运行时间。
        seconds = elapsed.TotalSeconds;  //  总秒数
        milliseconds = elapsed.TotalMilliseconds;  //  总毫秒数
        Console.WriteLine($"异步总耗时:{milliseconds},当前线程id:{Thread.GetCurrentProcessorId()}");

    }

    public string method1()
    {
        Thread.Sleep(1000);
        Console.WriteLine("method1 sleep 1000毫秒");
        Console.WriteLine("method1执行完毕!");
        return "method1";
    }

    public  string method2()
    {
        Thread.Sleep(2000);
        Console.WriteLine("method2 sleep 2000毫秒");
        Console.WriteLine("method2执行完毕!");
        return "method2";
    }

    public async Task<string> method1Async()
    {
        await Task.Run(() =>
        {
            Thread.Sleep(1000);
            Console.WriteLine($"method1Async sleep 1000毫秒,当前线程id:{Thread.GetCurrentProcessorId()}");
        });
        Console.WriteLine($"method1Async执行完毕!,当前线程id:{Thread.GetCurrentProcessorId()}");
        return "method1Async";
    }

    public async Task<string> method2Async()
    {
        await Task.Run(() =>
        {
            Thread.Sleep(2000);
            Console.WriteLine($"method2Async sleep 2000毫秒,当前线程id:{Thread.GetCurrentProcessorId()}");
        });
        Console.WriteLine($"method2Async执行完毕!,当前线程id:{Thread.GetCurrentProcessorId()}");
        return "method2Async";
    }

}

结果:

测试很多次,每次结果都是同步比异步快,采用async和awtia的异步编程方式到底有什么好处??大神能帮科普一下吗?

鹅是码农的主页 鹅是码农 | 菜鸟二级 | 园豆:245
提问于:2021-10-30 10:15
< >
分享
所有回答(4)
0

async/await 只是提高线程的利用率,比如对于 web 应用场景,借助 async/await 可以用50个线程支撑5000个并发

dudu | 园豆:30783 (高人七级) | 2021-10-30 10:47

由于额外的上下文切换,async/await 不但没有提速,反而会降速

支持(0) 反对(0) dudu | 园豆:30783 (高人七级) | 2021-10-30 10:52

在高并发以一(线程)敌百(请求)的场景下,async/await 的优势就会体现

支持(0) 反对(0) dudu | 园豆:30783 (高人七级) | 2021-10-30 10:56

为什么会提升并发呢?
比如50个并发进来,如果用同步,就是占用了50个线程而已。
但是如果用异步,可能需要60或100个线程参与进来,这种情况不是更容易导致线程池被用完吗?反而会导致后面的用户访问,因为线程池没有了需要排队等待,这样应该是减少并发才对。

支持(0) 反对(0) 鹅是码农 | 园豆:245 (菜鸟二级) | 2021-10-30 11:01

@小智互动: 1000个并发进来,只有50个线程
1)如果用同步,要等每个线程执行完当前请求,才能释放出来处理其他请求
2)如果用异步(await),执行当前请求的线程在遇到异步操作时,先将线程释放出来处理其他请求

比如,你需要做写代码与处理邮件这2件事
1)如果用同步,先写代码,build 代码时在那干等,等写好代码再处理邮件
2)如果用异步(await),也是先写代码,但是在等待build代码的时候用来处理邮件
哪个效率更高?

支持(0) 反对(0) dudu | 园豆:30783 (高人七级) | 2021-10-30 11:16

@dudu:
首选感谢您的回复,但是还有疑问。
如果按你这种需求,用异步的写法代码如下:
public async Task Execute()
{
await WtiteCodeAsync();
await SendMailAsync();
}
SendMailAsync需要等WtiteCodeAsync处理完了再处理,只是可能用了不同线程而已,浪费了一个线程,而且处理时间比同步还要长,所以这种写法提升不了效率吧。

要提示效率应该用下面这种多线程写法,如下:
public void Execute()
{
Task.Run(SendMail);
WtiteCode();
}
把邮件发送丢到其他线程中去处理,这样才能提升效率,而且处理邮件这块不占用主线程,还能让用户明显感觉到减少发送邮件的时间从而提示响应速度。

支持(1) 反对(0) 鹅是码农 | 园豆:245 (菜鸟二级) | 2021-10-30 11:24

@小智互动: 下面的代码与我举例想表达的是两回事

await WtiteCodeAsync();
await SendMailAsync();
支持(0) 反对(0) dudu | 园豆:30783 (高人七级) | 2021-10-30 11:37

@小智互动: 不好意思,时间所限,只能回答到这里

支持(0) 反对(0) dudu | 园豆:30783 (高人七级) | 2021-10-30 11:38
0

线程并不是为了提升单核单线程cpu效率,必须是建立在多线程多核cpu。即使多核多cpu,线程也不是多就效率高,取决于多方面因素。

花飘水流兮 | 园豆:13615 (专家六级) | 2021-10-30 12:12
0

你这样写测试代码肯定是异步的版本更慢啊,async异步多了线程上下文切换的开销。

可以考虑一下下面的情况
要请求10个或者一百个网页获得这10个或者100个网页的html内容,你用同步和异步比比试试?
或者我要复制10个或者100个文件情况

同步的话,用一个for循环,你请求完一个才能请求另一个(请求第一个时当前干活的线程就会被阻塞,其他啥事也干不了了);异步的话你Task.WhenAll(),会多线程同时发出n的请求,,速度肯定就上去了;发出网络请求是相对来说耗时的操作,如果发出并接收一个请求要1s,那么同步发出10个就要10s,那我如果同时并发(也就是用async)发出10个或100个呢?在你有多核处理器的时候,肯定是异步快嘛;有点像1个人吃一个馒头要5分钟,10个人吃10个馒头或者一个人吃10个馒头要几分钟的意思;只不过这里的1个馒头变成了发出1个http请求

Laggage | 园豆:878 (小虾三级) | 2021-10-31 21:44
0

上面代码都是同步执行的
加了await 表示等待执行结果

212的s | 园豆:431 (菜鸟二级) | 2021-11-08 17:36
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册