zoukankan      html  css  js  c++  java
  • C# 创建线程的多种方式之异步调用基础知识

    创建线程一种简单的方式是委托的异步调用,Delegate类提供了BeginInvoke方法,该方法可以传递委托类型定义的参数(所以BeginInvoke参数数量是可变的),另外还有2个固定的参数 回调函数委托AsynsCallBack和类型Object(如果不使用可直接赋值为null)。

    BeginInvoke() 的返回值为IAsynResult,通过它的IsComplete属性可以判断异步调用是否完成。

            static void Main(string[] args)
            {
                Func<int, int> act1 = new Func<int, int>(Calculate);
                Console.WriteLine("Main Start....");
                IAsyncResult ar = act1.BeginInvoke(20,null, null);
                while (!ar.IsCompleted)
                {
                    Console.WriteLine("Main is waiting");
                    Thread.Sleep(500);
                }
                int result = act1.EndInvoke(ar);
                Console.WriteLine("Result is " + result);
                Console.ReadLine();
            }
    
            private static int Calculate(int total)
            {
                int sum = 0;
                for (int i = 0; i < total;i++ )
                {
                    sum += i;
                    Thread.Sleep(100);
                }
                return sum;
            }

    运行返回结果:

    Main Start....
    Main is waiting
    Main is waiting
    Main is waiting
    Main is waiting
    Main is waiting
    Result is 190

    事实上,EndInvoke也是会等到异步调用结束,返回结果的。此外,IAsynResult的AsyncWaitHandle属性是WaitHandle类型,利用WaitOne()能够达到上述同样的效果,我觉得有一个好处就是可以利用WaitAll()等待多个异步调用同时完成:

            static void Main(string[] args)
            {
                Func<int, int> act1 = new Func<int, int>(Calculate);
                Func<int, int> act2 = new Func<int, int>(Calculate);
                Console.WriteLine("Main Start....");
                IAsyncResult ar1 = act1.BeginInvoke(20,null, null);
                IAsyncResult ar2 = act2.BeginInvoke(30, null, null);
                if(WaitHandle.WaitAll(new WaitHandle[]{ar1.AsyncWaitHandle,ar2.AsyncWaitHandle},5000))
                {
                    Console.WriteLine("Waiting is over");
                    
                }
                int result1 = act1.EndInvoke(ar1);
                int result2 = act2.EndInvoke(ar2);
                Console.WriteLine("Result1 is {0},Result2 is {1}", result1, result2);
                Console.ReadLine();
            }
    
            private static int Calculate(int total)
            {
                int sum = 0;
                for (int i = 0; i < total;i++ )
                {
                    sum += i;
                    Thread.Sleep(100);
                }
                return sum;
            }

    我声明了act1和act2两个委托对象,并同时进行异步调用,WaitHandle.WaitAll(new WaitHandle[]{ar1.AsyncWaitHandle,ar2.AsyncWaitHandle},5000) 等待同时完成,最后返回结果:

    Main Start....
    Waiting is over
    Result1 is 190,Result2 is 435

     除了以上2种方式返回运行结果,还可以使用AsynsCallBack回调,BeginInvoke()的最后一个参数可以用ar.Asynstate访问,以便在回调函数中使用,例如传递委托实例获取运行结果:

            static void Main(string[] args)
            {
                Func<int, int> act1 = new Func<int, int>(Calculate);
                Console.WriteLine("Main Start....");
                IAsyncResult ar1 = act1.BeginInvoke(20, new AsyncCallback(CalculateComplete), act1);
                while(!ar1.IsCompleted){
                    Console.WriteLine("Main is waiting");
                    Thread.Sleep(500);
                }
                Console.ReadLine();
            }
    
            private static int Calculate(int total)
            {
                int sum = 0;
                for (int i = 0; i < total;i++ )
                {
                    sum += i;
                    Thread.Sleep(100);
                }
                return sum;
            }
    
            private static void CalculateComplete(IAsyncResult ar)
            {
                Console.WriteLine("Counting is over...........");
                Func<int, int> act = ar.AsyncState as Func<int, int>;
                Console.WriteLine("Result is "+act.EndInvoke(ar));
            }

    运行结果:

    Main Start....
    Main is waiting
    Main is waiting
    Main is waiting
    Main is waiting
    Main is waiting
    Counting is over...........
    Result is 190

    回调函数是在委托线程中完成的,还可以使用Lamda表达式,更加简便,传入最后一个参数,因为Lamda表达式可以访问域外变量:

            static void Main(string[] args)
            {
                Func<int, int> act1 = new Func<int, int>(Calculate);
                Console.WriteLine("Main Start....");
                IAsyncResult ar1 = act1.BeginInvoke(20, ar => { Console.WriteLine("Result is " + act1.EndInvoke(ar)); }, null);
                while(!ar1.IsCompleted){
                    Console.WriteLine("Main is waiting");
                    Thread.Sleep(500);
                }
                Console.ReadLine();
            }
  • 相关阅读:
    Java内存模型
    mysql通过“延迟关联”进行limit分页查询优化的一个实例
    RabbitMQ(二):相应机制、持久化、负载均衡分发
    RabbitMQ(一):安装配置、用户权限
    S7.Net与西门子PLC通讯——纯新手必看
    [.net core] 创建和发布NuGet包 (dotnet CLI)
    [收藏]2018年10月最新全网可用接码打码平台 [若快已挂]
    如何写出无法维护的代码
    C# ——Parallel类
    .net语音播放,自定义播报文字
  • 原文地址:https://www.cnblogs.com/change-myself/p/11108980.html
Copyright © 2011-2022 走看看