C# .Net学习笔记—— 异步和多线程(Async和Sync)

一、概念

进程:一个程序运行时,占用的全部计算资源的总和

线程:1、程序执行流的最小单位;任何操作都是由线程完成的

2、线程是依托于进程存在的,一个进程可以包含多个线程;

3、线程也可以有自己的计算资源

多线程:多个执行流同时运行

1、CPU太快了,分时间片-一上下文切换(加载环境--计算-一保存环境)

微观角度,一个核同一时刻只能执行一个线程;宏观的来说是多线程并发

2、多CPU多核可以独立工作

4核8线程一核是物理的核线程是指虚拟核

同步:完成计算之后,再进入下一行

异步:不会等待方法的完成,会直接进入下一行非阻塞

C#异步和多线程有什么差别

多线程就是多个thread并发;

异步是硬件式的异步

异步多线程-thread pool task

二、同步异步简单案例

cs 复制代码
 private void buttonSync_Click(object sender, EventArgs e)
        {
            Log.Info($"S Start {Thread.CurrentThread.ManagedThreadId}");
            int j = 3;
            int k = 5;
            int m = j + k;
            for (int i = 0; i < 5; i++)
            {
                string name = string.Format($"**********S{i}*************");
                this.DoSomethingLong(name);
            }
            Log.Info($"S End");
        }

        private void buttonAsync_Click(object sender, EventArgs e)
        {
            Log.Info($"\nA Start {Thread.CurrentThread.ManagedThreadId}");
            Action<string> action = this.DoSomethingLong;
            for (int i = 0; i < 5; i++)
            {
                string name = string.Format($"**********A{i}*************");
                action.BeginInvoke(name, null, null);
            }
            Log.Info($"A End");
        }

        private void DoSomethingLong(string name)
        {
            Log.Info($"DoSomethingLong Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {name} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
            long result = 0;
            for (int i = 0; i < 100000000; i++)
            {
                result += i;
            }
            Thread.Sleep(2000);
            Log.Info($"DoSomethingLong End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {name} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
        }

同步:

异步:

从打印结果来看也能反映出,

同步:1、完成计算之后,再进入下一行。

2、同步方法卡界面,主(UI)线程忙于计算。

3、同步方法慢,只有一个线程干活
异步:1、不会等待方法的完成,会直接进入下一行非阻塞。

2、异步多线程方法不卡界面,主线程完事,计算任务交给子线程在做。

3、异步多线程方法快,因为多个线程并发运算

4、异步并不是线性增长,而是资源换时间,多线程也有管理成本

5、提升用户体验

6、并不是越多越好

7、最好是多个独立任务同时进行的使用

异步等待方式1:异步回调:

cs 复制代码
        private void buttonAysncCallback_Click(object sender, EventArgs e)
        {
            Log.Info($"DoSomethingLong Start {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
            Action<string> action = this.DoSomethingLong;

            AsyncCallback callback = ia => Log.Info($"计算完成。{Thread.CurrentThread.ManagedThreadId.ToString("00")}  {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
            action.BeginInvoke("AysncCallBack", callback, null);
            Log.Info($"DoSomethingLong End {Thread.CurrentThread.ManagedThreadId.ToString("00")} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
        }

从结果来看,异步回调action.BeginInvoke()可以得到一个AsyncCallBack,然后这个callBack再执行的委托。这样可以有效的控制我们线程的次序。

缺点:我想要全部计算都完成了再给用户返回结果,这种方法实现不了

异步等待方式2:线程等待

cs 复制代码
asyncResult.AsyncWaitHandle.WaitOne(); //等待任务完成
asyncResult.AsyncWaitHandle.WaitOne(); //等待任务完成
asyncResult.AsyncWaitHandle.WaitOne(1000); //等待;但是最多等待1000ns

异步等待方式3: EndInvoke()

cs 复制代码
        private void buttonTest_Click(object sender, EventArgs e)
        {
            Func<int> func = () =>
            {
                Thread.Sleep(2000);
                return DateTime.Now.Day;
            };
            Console.WriteLine($"func.Invoke()={func.Invoke()}");

            IAsyncResult asyncResult = func.BeginInvoke(r =>
            {
                Console.WriteLine(r.AsyncState);
            }, "哈啊哈哈");
            Console.WriteLine($"func.EndInvoke(asyncResult) = {func.EndInvoke(asyncResult)}");
        }
相关推荐
多多*1 分钟前
上传文件相关业务,采用策略模式+模版方法模式进行动态解耦
java·开发语言
晨非辰2 分钟前
【面试高频数据结构(四)】--《从单链到双链的进阶,读懂“双向奔赴”的算法之美与效率权衡》
java·数据结构·c++·人工智能·算法·机器学习·面试
im_AMBER2 分钟前
数据结构 03 栈和队列
数据结构·学习·算法
沐雨橙风ιε7 分钟前
Spring Boot整合Apache Shiro权限认证框架(实战篇)
java·spring boot·后端·apache shiro
左师佑图13 分钟前
Apache POI SXSSFWorkbook 报错“没有那个文件或目录”问题排查与解决方案
java·apache·excel
凸头20 分钟前
以AtomicInteger为例的Atomic 类的底层CAS细节理解
java·jvm·算法
艾派森24 分钟前
基于 Rokid CXR-M SDK 构建 AR 远程专家协作系统:从零实现眼镜端自定义 UI 与实时交互
java
我先去打把游戏先31 分钟前
VSCode通过SSH连接到Ubuntu虚拟机失败“找不到ssh安装”问题解决
笔记·vscode·单片机·嵌入式硬件·学习·ubuntu·ssh
cxyxiaokui00139 分钟前
🔥不止于三级缓存:Spring循环依赖的全面解决方案
java·后端·spring
UCoding44 分钟前
我们来学AI编程 -- vscode开发java
java·vscode·ai编程