这篇文章仅当总结之用,参考了很多前辈们的文章,加上了点点自己的理解
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); } } }
从图片可以看出 同步调用都是在一个线程当中
异步调用时再其他线程当中进行,特别注意理解回调函数
一切的操作主要需要用到Invoke方法,BeginInvoke,EndInvoke,深刻理解三个函数的意义和参数就能够理解同步和异步调用
希望对大家有用。
时间: 2024-10-04 02:55:35