C#1.0同步和异步调用

这篇文章仅当总结之用,参考了很多前辈们的文章,加上了点点自己的理解

C#的同步和异步线程是依靠委托来完成,主要需要用到委托的Invoke方法(实际上就是启动一个委托,委托默认同步),BeginInvoke和EndInvoke方法

所谓同步线就是阻塞当前线程来完成调用的方法,然后才继续调用当前线程的后面的操作,实际上都是在同一个线程中执行,效率不高。需要用到Invoke方法

异步线程不阻塞当前线程,而是把需要调用的方法加入线程池中,来同步执行,即同一时间两个及其以上的线程共同都在执行,效率很高。需要用到BeginInvoke和EndInvoke方法

流程图:

具体请看下面的源码和注释(PS:绝大多数总结都在注释当中了)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncRe
{
    class Program
    {
        static void Main(string[] args)
        {

            ImportantFun it=new ImportantFun();
            //依次演示同步调用  不完全异步调用  全异步调用
            it.Sync();
            it.TerribleAsync();
            it.Async();

        }
    }
     //定义一个委托类型
    public delegate int AddHandler(int x, int y);

    /// <summary>
    /// 演示同步调用和异步调用
    /// </summary>
    class ImportantFun
    {
        //被调用的方法
        private int Add(int x, int y)
        {
            //用于显示当前方法所在的线程
            Console.WriteLine("Add is running on thread"+Thread.CurrentThread.ManagedThreadId);

            //线程停滞6s
            Thread.Sleep(6000);
            return x + y;
        }
       
        /// <summary>
        /// 同步调用Add
        /// </summary>
       public void Sync()
        {
            Console.WriteLine("*********演示同步调用********");
            //打印当前方法所在的线程
            Console.WriteLine("Sync is running on thread"+Thread.CurrentThread.ManagedThreadId);
            AddHandler handler=new AddHandler(Add);
            //Invoke用于同步调用
            int Result = handler.Invoke(1, 2);
            Console.WriteLine("Add is Compete");
            Console.WriteLine("Result="+Result);
            Console.ReadKey();
        }
        /// <summary>
        /// 不完整的异步调用,具体见下面注释
        /// </summary>
        public void TerribleAsync()
        {
            Console.WriteLine("***********演示不完整异步调用**********");

            Console.WriteLine("TerribaleAsync is running on thread"+Thread.CurrentThread.ManagedThreadId);
            AddHandler handler=new AddHandler(Add);
            //异步调用一般用委托的BegInvoke和EndInvoke搭配在一起完成
            //BeginInvoke表示异步调用开始 返回一个表示调用状态的接口(IAsyncResult)
            IAsyncResult iar = handler.BeginInvoke(1, 2, null, null);
            //上面本该有4个参数,暂且把3,4号参数定为null

            Console.WriteLine("TerribaleAsync is running on thread" + Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine(iar.ToString());
            //EndInvoke表示异步调用时的方法,参数是IAsyncResult类型
            int result = handler.EndInvoke(iar);
            Console.WriteLine(result);
            Console.WriteLine("此种异步调用的方法有缺陷,在EndInvoke后面的方法同样被阻隔,只能保证Begin和End中间是异步");
            Console.ReadKey();
            //此种异步调用的方法有缺陷,在EndInvoke后面的方法同样被阻隔,只能保证Begin和End中间是异步

            //解决办法是利用BeginInvoke中的3号和4号参数,将EndInvoke列在回调函数当中
            //实际上就是为了避免EndInvoke出现在其他地方,利用BegingInvoke方法一次性调用它。见下面的方法
        }

        /// <summary>
        /// 完整异步调用 原理就是在beginInvoke中调用End
        /// </summary>
        public void Async()
        {
            Console.WriteLine("***********演示异步调用**********");
            Console.WriteLine("Async is running on thread"+Thread.CurrentThread.ManagedThreadId);
            AddHandler handler=new AddHandler(Add);
            //new AsyncCallback(Callback)回调函数,异步调用结束时,runtime会自动调用该函数
           //"Async parameter is me"作为回调参数 可以通过Async.AsyncState获取
            handler.BeginInvoke(1, 2, new AsyncCallback(CallBack), "Async parameter is me");
            //     上面                        一个委托,回调函数       回调参数

            Console.WriteLine("Async is running on thread "+Thread.CurrentThread.ManagedThreadId);
            //利用这步的输出结果可以验证是否是全异步。

            Console.ReadKey();
        }
        /// <summary>
        /// 回调函数
        /// </summary>
        /// <param name="iar"></param>
        private void CallBack(IAsyncResult iar)
        {
            Console.WriteLine("CallBack is running on thread"+Thread.CurrentThread.ManagedThreadId);
            //前者是异步操作的结果  后者代表过程中的所有
            AsyncResult Ar = (AsyncResult) iar;
            
            //获取原委托对象       注意强制转换
            AddHandler handler = (AddHandler) Ar.AsyncDelegate;
            //结束委托调用 得到结果
            int result = handler.EndInvoke(Ar);

            //输出上面的Begin中的第4个参数
            Console.WriteLine("The Async calling parameter is "+Ar.AsyncState);

           //输出结果
            Console.WriteLine("Result ="+result);
          
        }
    }
   

}

C#1.0同步和异步调用_第1张图片

从图片可以看出 同步调用都是在一个线程当中

异步调用时再其他线程当中进行,特别注意理解回调函数

一切的操作主要需要用到Invoke方法,BeginInvoke,EndInvoke,深刻理解三个函数的意义和参数就能够理解同步和异步调用

希望对大家有用。

你可能感兴趣的:(C#1.0同步和异步调用)