zoukankan      html  css  js  c++  java
  • C# 多线程系列之异步回调(委托)

    本文参考自C#基础:线程之异步回调(委托),纯属读书笔记

    在解析异步回调之前,先看同步回调的执行过程,以及代码原理。

    1、线程的同步执行

    同步执行:在主线程执行的时候,主线程调用一个其它方法,此时主线程阻塞,等待调用方法执行完成后主线程才能继续执行。

    代码如下:

        class Program
        {
            static void Main(string[] args)
            {
                for (int i = 1; i < 11; i++) {
                    if (i == 5) {
                        Console.WriteLine("调用TakeAWhile方法并等待其执行完成");
                        Console.WriteLine("开始执行TakeAWhile方法,时间:{0}", DateTime.Now);
                        int result = TakeAWhile(0, 6000);
                        if (result == 1) {
                            Console.WriteLine("TakeAWhile方法执行完成");
                        }
                        Console.WriteLine("TakeAWhile方法执行完毕,时间:{0}", DateTime.Now);
                    }
                    Thread.Sleep(30);
                    Console.WriteLine(i.ToString());
                }
            }
            static int TakeAWhile(int data, int time) {
                Thread.Sleep(time);
                return ++data;
            }
        }

    从上面的结果得出当程序开始调用TakeAWhile方法后,主线程阻塞,当TakeAWhile方法调用完毕之后,主线程又重新开始运行,这个过程就是线程的同步执行的过程.

    2、线程的异步执行

    what is 异步执行?

    异步执行:在主线程执行的时候,打开一个子线程,主线程不会像同步执行的那样等待子线程的结果返回后在执行,主线程会继续执行,当主线程需要子线程的运行结果时,主线程直接调用子线程的运行结果,如果子线程的运行结果还没有出来,那么主线程等待,直到子线程执行结束,主线程拿到子线程的运行结果,主线程在继续。

     class Program
        {
            static void Main(string[] args)
            {
                Func<int, int, int> fun = TakeAWhile;
                IAsyncResult ar = fun.BeginInvoke(0, 1000, null, null);//主线程调用子线程开始执行TakeAWhile方法,并给它传递了参数
                int times=1;
                while (!ar.IsCompleted)
                {
                    //当子线程没有完成之前,主线程可以在该while语句块内进行任何后续操作,而且不用等待子线程的结束
                    Console.WriteLine(times++);
                    Thread.Sleep(50);
                }
                int result = fun.EndInvoke(ar);//1秒之后我需要子线程的结果了,ok,从子线程中拿到结果
                Console.WriteLine("TakeAWhile方法结束,时间是:{0}", DateTime.Now);
                Console.WriteLine("result:{0}", result);
                Console.ReadKey();
            }
    
            static int TakeAWhile(int data, int times)
            {
                Console.WriteLine("TakeAWhile方法开始执行,时间是:{0}",DateTime.Now);
                Thread.Sleep(times);
                return ++data;
            }
        }

    从结果和代码进行分析,当通过BeginInvoke方法开始异步执行TakeAWhile方法,主线程继续执行,然后通过IsCompleted属性判断TakeAWhile是否执行完成,最后获取子线程的输出值,并输出其结果,整个过程主线程没有因为在执行子线程的原因,而造成阻塞

     注:因为多线程,导致了这个情况,开启子线程和执行子线程中的方法都需要时间,所以主线程的执行速度快于子线程,所以先输出了一个1;解决方法很简单,让主线程休息一会,等子线程先初始化完,代码如下:

    class Program
        {
            static void Main(string[] args)
            {
                Func<int, int, int> fun = TakeAWhile;
                IAsyncResult ar = fun.BeginInvoke(0, 1000, null, null);//主线程调用子线程开始执行TakeAWhile方法,并给它传递了参数
                Thread.Sleep(30);//休息一会
                int times=1;
                while (!ar.IsCompleted)
                {
                    //当子线程没有完成之前,主线程可以在该while语句块内进行任何后续操作,而且不用等待子线程的结束
                    Console.WriteLine(times++);
                    Thread.Sleep(50);
                }
                int result = fun.EndInvoke(ar);//6秒之后我需要子线程的结果了,ok,从子线程中拿到结果
                Console.WriteLine("TakeAWhile方法结束,时间是:{0}", DateTime.Now);
                Console.WriteLine("result:{0}", result);
                Console.ReadKey();
            }
    
            static int TakeAWhile(int data, int times)
            {
                Console.WriteLine("TakeAWhile方法开始执行,时间是:{0}",DateTime.Now);
                Thread.Sleep(times);
                return ++data;
            }
        }

    3、异步回调

    what is 异步异步回调?

    异步回调:主线程在执行的时候,打开一个子线程,主线程继续执行,当子线程执行完成的时候,主线程立即输出子线程的运行结果,主线程继续执行。

    class Program
        {
            static void Main(string[] args)
            {
                Func<int, int, int> fun = TakeAWhile;
                fun.BeginInvoke(0, 1000, TakesAWhileCallBack, fun);//异步调用TakeAWhile,并指定回调函数TakesAWhileCallBack
                for (int i = 0; i < 20; i++)
                {
                    Console.WriteLine(i.ToString());
                    Thread.Sleep(100);
                }
                Console.ReadKey();
            }
            static int TakeAWhile(int data, int times) {
                Console.WriteLine("TakeAWhile方法开始执行,时间是:{0}", DateTime.Now);
                Thread.Sleep(times);
                return ++data;
            }
            /// <summary>
            /// 回调函数
            /// </summary>
            /// <param name="fun">调用的委托</param>
            static void TakesAWhileCallBack(IAsyncResult fun)
            {
                if (fun == null)
                    throw new ArgumentNullException("fun");
                Func<int, int, int> dl = (Func<int, int, int>)fun.AsyncState;
                int result = dl.EndInvoke(fun);
                Console.WriteLine("我是回调函数返回的结果:{0}", result);
                Console.WriteLine("TakeAWhile执行完成,时间是:{0}", DateTime.Now);
            }
        }

  • 相关阅读:
    Windows打开软件老是弹出无法验证发布者
    SpringMvc接受特殊符号参数被转义
    时代更替中的方正
    你应该知道的c# 反射详解
    C#使用System.Data.SQLite操作SQLite
    C# 动态调用WebService
    C# API: 生成和读取Excel文件
    11个强大的Visual Studio调试小技巧
    .Net 垃圾回收和大对象处理
    Visual Studio原生开发的10个调试技巧(一)
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/6845708.html
Copyright © 2011-2022 走看看