C# .Net学习笔记—— 异步和多线程(await/async)

一、介绍

1、控制台测试await/async

2、C# 5.0 .Net framework4.5 CLR4.0 以后才有,本身是一种语法糖

二、基本测试

1、不加await测试。

cs 复制代码
        private async static Task TestAsync() 
        {
            Log.Info($"当前主线程id={Thread.CurrentThread.ManagedThreadId}");
            NoReturnNoAwait();
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(300);
                Log.Info($"Main Thread Task ManagedThreadID = {Thread.CurrentThread.ManagedThreadId}");
            }
        }
       

     private static async void NoReturnNoAwait() 
        {
            Log.Info($"NoReturn Sleep before await,ThreadID={Thread.CurrentThread.ManagedThreadId}");
            TaskFactory taskFactory = new TaskFactory();
            Task task = taskFactory.StartNew(() =>
            {
                Log.Info($"NoReturn Sleep before,ThreadID={Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(3000);
                Log.Info($"NoReturn Sleep after,ThreadID={Thread.CurrentThread.ManagedThreadId}");
            });
            Log.Info($"NoReturn Sleep after await,ThreadID={Thread.CurrentThread.ManagedThreadId}");
        }

2、加await测试。

cs 复制代码
        private async static Task TestAsync() 
        {
            Log.Info($"当前主线程id={Thread.CurrentThread.ManagedThreadId}");
            NoReturn();
            //NoReturnNoAwait();
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(300);
                Log.Info($"Main Thread Task ManagedThreadID = {Thread.CurrentThread.ManagedThreadId}");
            }
        }

        private static async void NoReturn() 
        {
            Log.Info($"NoReturn Sleep before await,ThreadID={Thread.CurrentThread.ManagedThreadId}");
            TaskFactory taskFactory = new TaskFactory();
            Task task = taskFactory.StartNew(() => 
            {
                Log.Info($"NoReturn Sleep before,ThreadID={Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(3000);
                Log.Info($"NoReturn Sleep after,ThreadID={Thread.CurrentThread.ManagedThreadId}");
            });
            await task;  //主线程到这里就返回了,执行主线程任务
            Log.Info($"NoReturn Sleep after await,ThreadID={Thread.CurrentThread.ManagedThreadId}");
        }

结果: 从打印出来的两种执行顺序来看,加了await以后,主线程运行到await这行就会执行

回主线程任务。而await后面的代码将由主线程或其他线程来执行

**原理:**await后面的代码,会被封装成委托,在await task之后成为回调(编译器功能,状态机实现) ,这个回调的线程是不确定的,可能是主线程,可能是子线程也可能是其他线程。

它可以等价于task.ContinueWith(t=>{}) 这里包起来

验证一下:

cs 复制代码
       private async void AwaitTest() 
        {
            //方法一:
            NoReturn();
            //方法二:
            TaskFactory taskFactory = new TaskFactory();
            Task task = taskFactory.StartNew(() =>
            {
                Log.Info($"NoReturn Sleep before,ThreadID={Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(3000);
                Log.Info($"NoReturn Sleep after,ThreadID={Thread.CurrentThread.ManagedThreadId}");
            });
            task.ContinueWith(t =>
            {
                callBack();
            });
            await task;
        }
        private static async void NoReturnNoAwait()
        {
            Log.Info($"NoReturn Sleep before await,ThreadID={Thread.CurrentThread.ManagedThreadId}");
            TaskFactory taskFactory = new TaskFactory();
            Task task = taskFactory.StartNew(() =>
            {
                Log.Info($"NoReturn Sleep before,ThreadID={Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(3000);
                Log.Info($"NoReturn Sleep after,ThreadID={Thread.CurrentThread.ManagedThreadId}");
            });
            Log.Info($"NoReturn Sleep after await,ThreadID={Thread.CurrentThread.ManagedThreadId}");
        }
        private void callBack()
        {
            Log.Info($"我是一个回调。。");
            Log.Info($"NoReturn Sleep after await,ThreadID={Thread.CurrentThread.ManagedThreadId}");
        }

三、返回值问题

1、不需要传值的时候,我们返回值就写成Task或者void都可以

2、需要传值的话 ,可以使用这种带泛型传值

四、小案例

cs 复制代码
       private void MainThread() 
        {
            Log.Info("主线程Start");
            Async();
            Log.Info($"aaa {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        }

        private async void Async()
        {
            Log.Info($"ddd {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
            await Task.Run(() =>
            {
                Thread.Sleep(500);
                Log.Info($"bbb {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
            });
            Log.Info($"ccc {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        }

猜测执行顺序:

1、打印主线程Start

2、主线程进入Async方法,打印ddd

3、碰到了await,主线程返回回去执行,打印aaa

4、子线程等待500毫秒后,并行打印bbb

5、最后回调打印ccc

公布结果:

相关推荐
xuhaoyu_cpp_java5 小时前
项目学习(三)分页查询
java·经验分享·笔记·学习
小宋加油啊7 小时前
机械臂抓取物体 PVN3D算法调研学习
学习·算法·3d
Xzh04238 小时前
AI Agent 学习路线(Java 后端方向)
java·人工智能·学习
Cloud_Shy6188 小时前
解读《Effective Python 3rd Edition》:从练气到老魔(第五章 Item 33 - 35)
开发语言·人工智能·笔记·python·学习方法
做cv的小昊8 小时前
计算机图形学:【Games101】学习笔记08——光线追踪(辐射度量学、渲染方程与全局光照、蒙特卡洛积分与路径追踪)
图像处理·笔记·学习·计算机视觉·游戏引擎·图形渲染·概率论
星恒随风8 小时前
C++ 类和对象入门(五):初始化列表、explicit 和 static 成员详解
开发语言·c++·笔记·学习·状态模式
sensen_kiss10 小时前
CPT304 SoftwareEngineeringII 软件工程 2 Pt.8 软件测试 (Software Testing)(上)
学习·软件工程
力学与人工智能10 小时前
PPT分享 | 洛桑联邦理工学院魏震:深度几何学习在工业设计优化中的应用
学习·优化·工业设计·深度几何学习·洛桑联邦理工学院
sensen_kiss12 小时前
CPT304 SoftwareEngineeringII 软件工程 2 Pt.9 软件测试 (Software Testing)(下)
学习·软件工程
wu_ye_m12 小时前
学习c语言第35天 函数声明和定义
c语言·开发语言·学习