首页 > 其他分享 >netcore之异步并不是多线程!

netcore之异步并不是多线程!

时间:2023-02-01 00:25:42浏览次数:36  
标签:异步 Task Console Thread netcore 线程 WriteLine 多线程

1、遇到await,线程的变化

遇到await会把当前线程返回且返回值就是await后面的Task,再从线程池随机取一个线程往下执行代码。

我们使用封装好的异步方法模拟写入大量字符串的耗时操作:

        static async Task Main(string[] args)
        {
            //原线程
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

            //模拟写入大量字符串的耗时操作
            StringBuilder str = new StringBuilder();
            for (int i = 0; i < 1000; i++)
            {
                str.Append("Hello World!");
            }
            await File.WriteAllTextAsync(@"C:\Users\张跑跑\Desktop\net\async\1.txt", str.ToString());

            //异步之后线程
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        }

结果显示前后线程不一致

那么问题来了,首先会随机到原来的线程吗?答案是会的,发生在异步操作所需时间很少的情况下。现在,我们仅仅把上述代码的循环次数缩短

        static async Task Main(string[] args)
        {
            ......
          	//降为10次
            for (int i = 0; i < 10; i++)
            {
                str.Append("Hello World!");
            }
          	......
        }

可以看到,线程未改变。(作一个比喻就是,前台(当前线程)放你进店,服务员(新线程)把你领到座位上后忙自己的事,所以你点完菜可能是另一个服务员传,但服务员还没走远,你就点完了菜,那只好她继续上传菜单了)

参考:
https://zhuanlan.zhihu.com/p/343235838
https://www.cnblogs.com/jiangchengbiao/p/10040899.html

2、异步不等于多线程

自定义的异步方法并不会自动在新线程中执行,除非手动new线程、或者委托、或使用封装好的异步方法

我们模拟一个自定义异步方法

        static async Task Main(string[] args)
        {
            //原线程
            Console.WriteLine("原线程:" + Thread.CurrentThread.ManagedThreadId);
            double r = await TestAsync();
            Console.WriteLine(r);
            //异步之后线程
            Console.WriteLine("异步后线程:" + Thread.CurrentThread.ManagedThreadId);
        }


        static async Task<double> TestAsync()
        {
            //异步中线程
            Console.WriteLine("异步后线程:" + Thread.CurrentThread.ManagedThreadId);
            double n = 0;
            Random random = new Random();
            for (int i = 0; i < n * n; i++)
            {
                n = random.NextDouble();
            }
            return n;
        }

结果是线程未改变

现在我们模拟一个委托

        static async Task Main(string[] args)
        {
            //原线程
            Console.WriteLine("原线程:" + Thread.CurrentThread.ManagedThreadId);
            double r = await TestAsync1();
            Console.WriteLine(r);
            //异步之后线程
            Console.WriteLine("异步后线程:" + Thread.CurrentThread.ManagedThreadId);
        }


        static async Task<double> TestAsync()
        {
            return await Task.Run(() =>
            {
                //异步中线程
                Console.WriteLine("异步后线程:" + Thread.CurrentThread.ManagedThreadId);
                double n = 0;
                Random random = new Random();
                for (int i = 0; i < n*n; i++)
                {
                    n = random.NextDouble() ;
                }
                return n;
            });
        }

可以看到。此时的线程发生了改变

并且注意到,异步中和异步结束后的线程还是一致,前面提到是随机,难道真这么巧?在多次改变for的次数下,貌似不是随机的,难道除了自定义现在连委托也,但具体情况在我的认知盲区!!!我们知道切换线程是要消耗存在大量程序上下文开销,所以就猜想这是net给优化了吧

# async+await 和同步执行有什么好处,都是要一个线程干活,一条龙干到底不好吗,非得自己干到一半交给另一个线程去干,别人干活不用开销吗?

这个问题的关键就是有些IO事情真的不需要CPU派一个线程去干,去了也干不了。比如读写文件,以往同步方法时,派一个线程去读写点东西的时候,这个线程肯定是等在那的,读写这个事情是硬盘去做的,线程就是个使者,告诉硬盘要做哪些事就行,硬盘干完活就告诉线程,线程拿着结果开心地继续干下面的活。那异步就是线程通知硬盘去读写后自己就回去该干嘛干嘛去,不必等在硬盘家门口等消息。硬盘读写的时候,这个线程是非阻塞的,可以干其他活,提高效率。硬盘读写完,会通知CPU,叫他派一个线程来拿结果,(如果框架是单线程的,那还是这个线程过来)这个线程拿到结果后会继续执行之前那个线程未干完的活,至于上下文信息,底层会交代好,不在这里讨论,太深。这个IO事情有很多,比如访问数据库,请求网络等。

标签:异步,Task,Console,Thread,netcore,线程,WriteLine,多线程
From: https://www.cnblogs.com/long-live/p/aw.html

相关文章

  • 没有async,await标志的异步方法
    1.我们看到有些异步方法源码内部未出现async,await的之前我们就知道,当使用了async,await时,所有的await代码会被反编译成一个一个的状态机以及生产一个异步类,效率远不如普通......
  • 异步任务队列
    异步任务队列Task.WhenAll(List<Task>)等List中所有的异步任务完成后才算完成Task.WhenAny(List<Task>)List中某个完成就完成较常用的是Task.WhenAll(List<Task>)不aw......
  • i++在多线程下的原子性问题
     staticinti=0;@TestvoidiTest()throwsInterruptedException{Threadt1=newThread(()->{for(intj=0;j<50000;......
  • [Python] 爬虫系统与数据处理实战 Part.3 多线程和分布式
    为什么用快反爬虫 多线程复杂性资源、数据的安全性:锁保护原子性:数据操作是天然互斥的同步等待:wait()、notify()、notifyall()死锁:多个线程对资源互锁容灾:任......
  • OpenHarmony stage worker 多线程
    作者:徐金生OpenHarmony存在一个与主线程并行的独立线程--Worker。对于处理耗时操作且不阻塞主线程起到了重要的作用,并且多个线程并发可以提高CPU和内存的利用率。在实际开......
  • 多线程--消费者与生产者实例
    多线程实例1.消费者与生产者实例(管程法)产品、消费者、生产者、缓冲区产品,保证有一个唯一标识即可消费者继承Thread,注册缓冲区,从缓冲区消费生产者继承Thread,注册缓冲......
  • java多线程基础小白指南--线程的状态
    线程的状态比较混乱,网上的资料也是五花八门,这时候就要参考注意截图中的最后一句话,很多人把jvm中线程状态与实际上的os线程状态搞混了,所以才会有很多乱七八糟的状态出现。......
  • openresty 中主要的几种异步执行方式
    openresty中主要的几种异步执行方式openresty宣传是同步非阻塞(100%non-blocking)的,基于事件通知的Nginx给我们带来了足够强悍的高并发支持。可以让我们可以使用同......
  • Linux的多线程下使用c/c++调用Python方法示例
    首先,所有python的函数都是用extern"C"定义的,因此对于C和C++,其使用是一样的。c语言调用python必须要有的API(不管有没有多线程):  PyRun_SimpleString//执行一段......
  • 通过一个示例形象地理解C# async await异步
    前言相信大家看过不少讲C#asyncawait的文章,博客园就能搜到很多,但还是有很多C#程序员不明白。如果搞不明白,其实也不影响使用。但有人就会疑惑,为什么要用异步?我感觉它更......