c#异步编程实现

同步&异步

既然说到异步编程那就说下异步编程和同步编程的区别。
同步:简单来说就是按顺序执行,例如登录过程必须输入用户名、密码再点击登录
第一步:输入用户名
第二步:输入密码
第三部:点击登录
这就是一个同步过程
异步:异步可以说是同时进行多个任务,相互不干扰,第二个任务的执行不需要等待第一个任务执行。
例如: 下载一个Oracle的安装包,安装过得人应该知道 Oracle的安装包一般是有两个构成,必须两个都下载然后解压在一起才可以开始安装。这里我们下载的过程肯定是不需要先下载安装包1再下载安装包2,而是一起下载,等两个都下载好了进行安装。
我们可以对比下异步和同步所需时间,还是以下载Oracle安装包为例。
假设下载安装包1需要6s,下载安装包2需要4s
同步的操作: 一.下载安装包1 二.下载安装包2 所需时间:6+4 =10s
异步的操作:同时下载安装包1安装包2(排除网络原因) 所需时间应算最长下载时间,所需时间:6s

代码实现

简单异步实现

下面我们直接用代码来呈现异步过程,用一个小demo来实现。
在这里插入图片描述

    public partial class Form1 : Form
    {
        //异步编程:基于委托实现
        public Form1()
        {
            InitializeComponent();
        }
        //[1]定义一个委托
        public delegate int MyCalulator(int num);
        //[2]根据委托实现方法
        private int ExecuteTask1(int num)
        {
            System.Threading.Thread.Sleep(5000);
            return num * num;
        }
        private int ExecuteTask2(int num)
        {
            return num * num;
        }
        //同步调用
        private void button1_Click(object sender, EventArgs e)
        {
            this.label1.Text = ExecuteTask1(10).ToString();
            this.label2.Text = ExecuteTask2(10).ToString();
        }

        //[3]异步调用
        private void button2_Click(object sender, EventArgs e)
        {
            MyCalulator objMycal = ExecuteTask1;//定义委托变量,并引用对应方法
            //1.异步调用任务 实际调用参数 回调函数 回调函数入参
            IAsyncResult result =objMycal.BeginInvoke(10,null,null);
            this.label1.Text = "正在计算请稍等。。。";
            //2.并行执行其他任务
            this.label2.Text = ExecuteTask2(200).ToString();
            //3.获取异步执行结果
            int r = objMycal.EndInvoke(result);
            this.label1.Text = r.ToString();
        }
    }

异步是基于委托实现的所以我们第一步需要定义一个委托

 public delegate int MyCalulator(int num);

第二步根据委托实现方法

private int ExecuteTask1(int num)
        {
            System.Threading.Thread.Sleep(5000);
            return num * num;
        }

第三部编写异步方法

private void button2_Click(object sender, EventArgs e)
        {
        	//通过委托调用方法ExecutrTask1
            MyCalulator objMycal = ExecuteTask1;//定义委托变量,并引用对应方法
            //1.异步调用任务 实际调用参数 回调函数 回调函数入参
            IAsyncResult result =objMycal.BeginInvoke(10,null,null);
            this.label1.Text = "正在计算请稍等。。。";
            //2.并行执行其他任务
            this.label2.Text = ExecuteTask2(200).ToString();
            //3.获取异步执行结果
            int r = objMycal.EndInvoke(result);
            this.label1.Text = r.ToString();
        }

编写异步方法的流程在注释里都写出来了,下来重点介绍下其中的几个方法
BeginInvoke函数

IAsyncResult result =objMycal.BeginInvoke(10,null,null);

委托类型的BeginInvoke(<输入和输出变量>,AsyncCallBack callback , object ayncState)方法 :异步调用的核心
第一个参数 表示委托对应的方法实参
第二个参数 回调函数,表示异步调用结束后,自动调用的方法
第三个参数 用于向回到函数提供相关的参数信息
返回值:IAsyncResult->异步操作状态接口,封装了异步执行中的参数

在这里我们只是实现一个简单的异步,并没有使用回调方法,而是直接取了返回值。在后面的文章中会使用回调方法。
下面我们可以看下demo的运行情况
在这里插入图片描述
可以看到单机同步后因为第一个计算方法需求等待,所以第二个结果基本是与第一个结果同时出现的,而使用异步结果2直接被计算了出来,之后结果1经过等待时间后被计算。

异步方法采用回调函数

还是用一个demo来讲解异步方法使用回调函数,先看下demo的运行效果
在这里插入图片描述
这里我把输出放在了控制台上,先看代码吧

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            objMyCal = new MyCalculator(ExecuteTask);
        }
        //【3】创建委托变量
        private delegate int MyCalculator(int num, int ms);
        private int ExecuteTask(int num,int ms)
        {
            System.Threading.Thread.Sleep(ms);
            return num * num;
        }
        //【1】声明委托
        MyCalculator objMyCal = null;
        private void button1_Click(object sender, EventArgs e)
        {
            //发布任务
            for(int i = 1; i < 11; i++)
            {
                //开始异步执行
                objMyCal.BeginInvoke(10 * i, 1000 * i, MyCallBack,i);
                //到最后一个参数i给回调函数的字段AsyncState赋值,如果数据很多可以定义成类或结构
            }
        }

        private void MyCallBack(IAsyncResult result)
        {
            int res = objMyCal.EndInvoke(result);
            //显示异步调用结果:result.AsyncState字段用来封装回调函数自定义参数,object类型
            Console.WriteLine($"第{result.AsyncState.ToString()}个计算结果为{res}");
        }
    }

通过上面的代码可以看到,我们每次给睡眠时间增加1000毫秒,如果不采用异步的话,执行时间应该是1+2+3+…+10=55s.然而我们这里采用异步只需要10s左右,大部分流程与上面相同,有不同之处的是这里

objMyCal.BeginInvoke(10 * i, 1000 * i, MyCallBack,i);

这里的第三个参数位置我们添加了回调方法MyCallBack

 private void MyCallBack(IAsyncResult result)
        {
            int res = objMyCal.EndInvoke(result);
            //显示异步调用结果:result.AsyncState字段用来封装回调函数自定义参数,object类型
            Console.WriteLine($"第{result.AsyncState.ToString()}个计算结果为{res}");
        }

在第四个参数位置输入了给回调函数使用的参数,这里的类型是object型,可以传入任何类型的参数,这个参数传入后会保存在IAsyncResult的AsyncState中,在回到函数中我们也进行了调用的示范,在如下这句话中result.AsyncState.ToString()

Console.WriteLine($"第{result.AsyncState.ToString()}个计算结果为{res}");

这段代码就是使用了回调函数的异步调用。

异步编程总结

1.异步编程是建立在委托的基础上的一种编程的方法
2.异步调用的每个方法都是独立的线程中执行的。因此,本质上就是一种多线程程序,是简化的多线程
3.比较适合在后头运行较为耗时的《简单任务》,并且任务之间要求相互独立,任务中不应该有直接访问可视化控件的代码
3.如果后台任务要求必须按照特定的顺序执行,或者访问共享资源,则异步编程不太适合,应该选择多线程开发技术。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Maybe_ch

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值