zoukankan      html  css  js  c++  java
  • C#入门面向对象编程(异步编程&多线程)

    异步编程

    实例一:同步编程VS异步线程

    分别用同步和异步方式计算一个数的平方。为了显示效果定义两个方法,其中一个方法延迟执行

     编码如下:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    namespace AsyncDemo
    {
        public partial class FrmMain : Form
        {
            public FrmMain()
            {
                InitializeComponent();
            }
            /// <summary>
            /// 同步执行按钮
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnClick1_Click(object sender, EventArgs e)
            {
                this.lblCount1.Text = this.ExerTask1(10).ToString();
                this.lblCount2.Text = this.ExerTask2(10).ToString();
            }
            //[2]根据委托定义方法
            private int ExerTask1(int num)
            {
                System.Threading.Thread.Sleep(5000);//延迟5秒执行
                return num * num;
            }
            private int ExerTask2(int num)
            {
                return num * num;
            }

            private void FrmMain_Load(object sender, EventArgs e)
            {

            }
            /// <summary>
            /// 异步执行
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnClick2_Click(object sender, EventArgs e)
            {
                //[3]异步调用
                CalculateDelegate objCalculateDelegate = ExerTask1;//创建委托对象并指向第一个方法
                IAsyncResult result = objCalculateDelegate.BeginInvoke(10, null, null);//异步调用任务
                //委托类型的BeginInvoke(<输入和输出变量>(委托方法中的参数),AsyncCallback callback,object asyncState)方法:异步调用的核心
                //第一个参数10,表示委托对应的实参
                //第二个参数callback:回调函数,表示异步调用后自动调用的函数
                //第三个参数asyncState:用于向回调函数提供参数信息
                //返回值:IAsyncResult 异步操作状态接口,封装了异步执行中的参数
                this.lblCount1.Text = "正在计算,请稍等...";


                //同时执行另一个方法
                this.lblCount2.Text = this.ExerTask2(10).ToString();

                //获取异步执行结果
              
                int res = objCalculateDelegate.EndInvoke(result);
                //委托类型的EndInvok()方法:借助于IAsync接口对象,不断的查询异步调用是否结束
                //该方法知道异步调用的方法所有参数,所以,异步调用完毕后,取出异步调用的结果作为返回值
                this.lblCount1.Text = res.ToString();


            }
        }
        //[1]声明委托
        public delegate int CalculateDelegate(int num);
    }
    实例二:演示异步回调函数的应用,控制台延迟显示数字平方计算值10次

    执行结果:

    编码如下:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    namespace AsyncDemo2
    {
        /// <summary>
        /// 演示异步回调函数的应用,控制台延迟显示数字平方计算值10次
        /// </summary>
        public partial class FrmMain : Form
        {
            public FrmMain()
            {
                InitializeComponent();
                //[3]初始化委托变量
                this.objCal = new CalculateDelegate(Calculate);
            }
            //[2]根据委托定义方法
            private int Calculate(int num,int ms)
            {
                System.Threading.Thread.Sleep(ms);
                return num * num;
            }
            //[3]创建委托对象

            CalculateDelegate objCal = null;
            /// <summary>
            /// 异步调用回调函数 同时执行多个任务
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnAsyncCallback_Click(object sender, EventArgs e)
            {
                //[4]异步调用
                for(int i = 1; i < 11; i++)
                {
                    //开始异步执行,并封装回调函数
                   objCal.BeginInvoke(10 * i, 1000 * i, CalCallback, i);
                    //最后一个参数i给回调函数的字段AsyncState赋值,这个字段是object类型
                }

            }
            //[5]编写回调函数
            private void CalCallback(IAsyncResult result)
            {
                int res = objCal.EndInvoke(result);
                Console.WriteLine("第{0}次的输出结果为:{1}", result.AsyncState.ToString(), res.ToString());
            }
        }
        //[1]声明委托
        public delegate int CalculateDelegate(int num, int ms);
     
    }

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

    多线程

    实例三:在控制台同时显示两个线程的输出内容

    运行结果:

     代码如下:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Threading;

    namespace TheadTest
    {
        /*
         *进程:一个正在运行的程序就是一个进程,操作系统根据进程分配各种资源(内存...)
         *线程:操作系统为了提高效率会将一个进程分为多个线程,并按照线程来分配CPU执行时间
         *线程特点:在具有多个CPU的计算机中,可以并行执行。1CPU 12线程 轮循假多线程
         *Thread类:表示托管线程,每个Thead对象都代表一个托管线程,每个托管线程都对应一个函数。
         *ProcessThread类型:和操作系统本地线程一致
         *TheadStart()方法定义:public delegate void  ThreadStart();
        */
        public partial class FrmThead : Form
        {
            public FrmThead()
            {
                InitializeComponent();
            }

            //任务一:循环输出一个结果
            private void btnThead1_Click(object sender, EventArgs e)
            {
                Thread objThread1 = new Thread(delegate ()
                  {
                      int a = 0;
                      for(int i = 1; i <= 20; i++)
                      {
                          Console.WriteLine((a+i)+" ");
                          Thread.Sleep(500);
                      }
                  });//匿名方法定义委托方法
                objThread1.IsBackground = true;//定义为后台线程
                objThread1.Start();
            }
            //任务二
            private void btnThead2_Click(object sender, EventArgs e)
            {
                Thread objThread2 = new Thread(()=>
                {
                    int a = 0;
                    for (int i = 1; i <= 50; i++)
                    {
                        Console.WriteLine("-----------a"+i+"------------");
                        Thread.Sleep(100);
                    }
                });//Lamada定义委托方法
                objThread2.IsBackground = true;//定义为后台线程
                objThread2.Start();

            }
        }
    }
    实例四:跨线程可视化控件。两个线程的控件不能直接访问需要借助Invoke()方法

    代码如下:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    namespace CrossThreadVistControl
    {
        public partial class FrmCrossThreadVist : Form
        {
            public FrmCrossThreadVist()
            {
                InitializeComponent();
            }

            private void btnThread1_Click(object sender, EventArgs e)
            {
                Thread objthread1 = new Thread(() =>
                  {
                      int a = 0;
                      for (int i = 0; i <= 100; i++)
                      {
                          a += i;
                          if (this.lblCount1.InvokeRequired)//判断是否调用Invoke方法
                          {
                              //Invoke()方法第一个参数是返回值为void的委托,第二个参数是委托对应方法传递参数
                              //Action是有一个参数但是没有返回值的委托集合变量
                              this.lblCount1.Invoke(new Action<string>(s => { this.lblCount1.Text = s; }), a.ToString());
                          }
                          Thread.Sleep(200);
                      }

                  });
                objthread1.IsBackground = true;
                objthread1.Start();
            }

            private void btnThread2_Click(object sender, EventArgs e)
            {
                Thread objthread2 = new Thread(() =>
                {
                    int a = 0;
                    for (int i = 0; i <= 100; i++)
                    {
                        a += i;
                        if (this.lblCount2.InvokeRequired)//判断是否调用Invoke方法
                        {
                            this.lblCount2.Invoke(new Action<string>(s => { this.lblCount2.Text = s; }), a.ToString());
                        }
                        Thread.Sleep(200);
                    }

                });
                objthread2.IsBackground = true;
                objthread2.Start();
            }
        }
    }

  • 相关阅读:
    Python pynput监听键盘
    ProceedingJoinPoint pjp 获取不到方法上
    springcloud- FeginClient 调用统一拦截添加请求头 RequestInterceptor ,被调用服务获取请求头
    多线程-Thread、Runnable 创建线程和调用过程分析
    spring --解析自定义注解SpringAOP(配合@Aspect)
    spring 核心接口之 Ordered
    图标文字
    文字展开和收起
    查找字符串中给定字符串的所有位置
    随机函数与JSON
  • 原文地址:https://www.cnblogs.com/cuig/p/8910526.html
Copyright © 2011-2022 走看看