zoukankan      html  css  js  c++  java
  • 多线程与异步编程知识简单总结

    一些基本概念:

    运行一个程序所需要的所有资源就是一个进程。

    一个进程可以有多个线程,且最少有一个线程。

    线程是cpu调度的最小单位。

    可以把进程理解为一个公司,一个线程理解为公司里的一个员工。

    应用程序域:可以在一个进程中启动多个应用程序(在一个exe程序中再启动另一个exe程序,在任务管理器中只启动了一个进程~)。

     

    什么时候用多线程呢?

      1、一个任务需要较长的耗时,但是我们不想等,想要在这个任务执行的时候,同时干点别的事

      2、cpu比较闲,其他的操作却比较忙的时候可以使用多线程。

      3、为了防止界面卡死,可以使用多线程。

     下面上代码:

    1、启动一个线程 ,执行一个无参数的方法

    // 1.创建一个线程对象,把DoWhile方法传递进去,表示该线程启动后会执行这个方法
    t1 = new Thread(new ThreadStart(DoWhile));
    
    t1.IsBackground = true;// 把当前线程设置为后台线程,后台线程在所有前台线程执行完毕后自动退出。默认创建的进程都是“前台线程”
    
    // 2.启动这个线程 
    t1.Start(); // 向操作系统请求启动线程。
    
    private void DoWhile() 
    {   
      while (true)   
      {     
        Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));     
        Thread.Sleep(500);   
      }
    }
    

      

    2、启动一个线程,执行一个需要一个参数的方法

        Thread t1 = new Thread(new ParameterizedThreadStart(M2));
        t1.Start(100);        
    
    
        static void M2(object n)
            {
                int max = (int)n;
                int sum = 0;
                for (int i = 1; i < max; i++)
                {
                    sum += i;
                }
                Console.WriteLine(sum);
            }
    

    3、启动一个线程,执行带参数的方法,几个参数都行!

        //把要执行的方法封装到一个类中
        //将执行方法所需要的参数封装为类的属性
        //将该方法改为一个无参的方法,原本方法中的参数用类的属性代替。
        //为这个类的属性赋值,就相当于为方法传参
        MyClass mc = new MyClass();
        mc.Number = 101;
        Thread t1 = new Thread(new ThreadStart(mc.M3));
        t1.Start();
    
    
        public class MyClass
        {
            public int Number
            {
                get;
                set;
            }
            public void M3()
            {
                int sum = 0;
                for (int i = 1; i < this.Number; i++)
                {
                    sum += i;
                }
                Console.WriteLine(sum);
            }
        }
    

    4、启动一个线程,执行带返回值的方法

                // 创建一个后台执行者对象
                BackgroundWorker backWorker = new BackgroundWorker();
                // 设置该对象在后台执行的方法
                backWorker.DoWork += new DoWorkEventHandler(backWorker_DoWork);
                // 设置后台方法执行完毕后触发的事件
                backWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backWorker_RunWorkerCompleted);
                // 开始执行
                backWorker.RunWorkerAsync(new int[] { 1, 100 });
    
            // 后台执行的方法
            static void backWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                if (e.Argument != null)
                {
                    int[] arr = e.Argument as int[];
                    //将返回值赋给e.Result
                    e.Result = Sum(arr[0], arr[1]);
                }
            }
    
            // 后台方法执行完毕后触发的事件
            static void backWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                Console.WriteLine("最后输出结果是:{0}", e.Result);
            }
    

    5、后台线程改变界面

    public delegate void ShowMsgDelegate(string msg);
     
    private void ShowMsg(string msg)
    {
      label1.Text = msg;
    }
    
        
    ShowMsgDelegate showMsgDelegate= new ShowMsgDelegate(ShowMsg);
    string msg="hello";
    Invoke(showMsgDelegate,msg);  

     6.异步编程

         public delegate int HaoShiDelegate(int startValue);
    
            public HaoShiDelegate HaoShi = HaoShiMethod;
            private void button1_Click(object sender, EventArgs e)
            {
                // 第一个参数为执行异步方法需要的参数
                // 第二个参数为回调方法
                // 第三个参数为传递给回调方法的一些信息,参数类型为object,如果需要传递多个信息,则可以将这些信息封装到一个类中。
                HaoShi.BeginInvoke(1000, CallBackMethod, "啦啦啦啦啦啦");
            }
    
            private static int HaoShiMethod(int startValue)
            {
                int sum = startValue;
                for (int i = 0; i < 100; i++)
                {
                    sum += i;
                }
                Thread.Sleep(5000);
                return sum;
            }
    
            // 回调函数只能有一个参数,并且参数的类型只能是IAsyncResult
            private void CallBackMethod(IAsyncResult r)
            {
                // 获取原始的委托变量
                AsyncResult result = (AsyncResult)r;
                HaoShiDelegate d = (HaoShiDelegate)result.AsyncDelegate;
    
                // 获取BeginInvoke中传递的最后一个object参数
                string lastParam = (String)result.AsyncState;
           // 通过调用原始委托变量的EndInvoke方法获得异步方法的返回值。
    int num = d.EndInvoke(r); MessageBox.Show("耗时方法的返回值是:" + num + " 最后一个参数是 " + lastParam); }

      

    摇奖机小练习:https://files.cnblogs.com/files/FangZhaohu/%E6%91%87%E5%A5%96%E6%9C%BA%E5%B0%8F%E7%BB%83%E4%B9%A0.zip

     异步编程小demo:https://files.cnblogs.com/files/FangZhaohu/%E5%BC%82%E6%AD%A5%E7%BC%96%E7%A8%8B%E5%B0%8Fdemo.zip

      

  • 相关阅读:
    html中的块级元素、行内元素
    ptyhon_opencv 图像的基本操作
    正则表达式总结 2017.1.6
    HashMap 中的 entrySet()使用方法 2016.12.28
    (转)Redis持久化的几种方式
    负数与二进制换转方法
    (转)2019JAVA面试题附答案(长期更新)
    Java后端技术面试汇总(第一套)
    (转)Dubbo服务暴露过程源码分析
    Dubbo消费方服务调用过程源码分析
  • 原文地址:https://www.cnblogs.com/FangZhaohu/p/4594235.html
Copyright © 2011-2022 走看看