C#同步和异步调用

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

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

C#同步和异步调用的相关文章

ABAP中的同步和异步调用

ABAP 的 CALL FUNCTION 类似于 Java/.NET 中的本地或远程方法调用.CALL FUNCTION 可以分为四种:1. Synchronous RFC (sRFC) - 同步调用2. Asynchronous RFC (aRFC) - 异步调用3. Transactional RFC (tRFC) - 保证 Transaction 数据一致性的调用4. Queued RFC (qRFC) - 用一个对列序列化的 tRFC本文很好地介绍了前面两种,也是最常用的两种.SAP H

[SAP ABAP开发技术总结]Function远程、同步、异步调用

目录导航 声明:原创作品,转载时请注明文章来自SAP师太博客,并以超链接形式标明文章原始出处,否则将追究法律责任!原文出自: 20.1.         Function调用... 233 20.1.1.     更新FM:LUW.. 233 20.1.2.     RFC函数:远程调用... 234 20.1.2.1.           同步... 234 20.1.2.2.           异步... 234 20.1.2.2.1.       事务性RFC调用... 234 20.1

C#:Func的同步、异步调用(转)

实际开发中,对于一些耗时较长的操作,我们往往会将其封装成异步方式调用,以加速系统响应或改善用户体验,下面是一个示例: 有一个现成的类MyMath,里面有一个Add方法: 1 public class MyMath 2 { 3 4 public int Add(int a, int b) 5 { 6 System.Threading.Thread.Sleep(5000); 7 return a + b; 8 } 9 10 } 对Add方法做下封装,对了对比,同时提供“同步调用”与"异步调用&quo

python 37 同步、异步调用

目录 1. 阻塞与非阻塞 2. 同步与异步 2.1 异步调用 2.2 同步调用 2.3 异步调用回收的第一种方式 3. 异步调用+回调函数 3.1 requests模块 3.2 异步调用回收的第二种方式 1. 阻塞与非阻塞 执行的角度: ? 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(如遇到io操作).函数只有在得到结果之后才会将阻塞的线程激活. ? 非阻塞:程序没有遇到IO阻塞,或者程序遇到IO,通过某种方式,让CPU强行运行程序. 2. 同步与异步 发布的角度: ? 同步调用:在发

Ajax的同步和异步调用

jquery的async:false,这个属性 默认是true:异步,false:同步. $.ajax({ type: "post", url: "path", cache:false, async:false, dataType: ($.browser.msie) ? "text" : "xml", success: function(xmlobj){ } }); 有了这个属性可以相对的减少代码运行书序问题,但是如果用的太多

Axis2之异步调用

本章主要介绍axis2接口的异步调用方式. 一般情况下,我们使用同步方法(invokeBlocking)调用axis2接口,如果被调用的WebService方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止.使用同步方法来调用WebService虽然很直观,但当WebService方法由于各种原因需要很长时间才能返回的话,就会使客户端程序一直处于等待状态,这样用户是无法忍受的. 当然,我们很容易就可以想到解决问题的方法,这就是多线程.解决问题的基本方法是将访问WebService的任务交由

一位牛人的多线程和异步调用文章

转自小顾问原文 一位牛人的多线程和异步调用文章 首先申明:这篇文章不是我写的,我看到的一位牛人的,自己慢慢的消化了…… 摘要:本章讨论与智能客户端应用程序中多线程的使用有关的问题.为了最大限度地提高智能客户端应用程序的响应能力,需要仔细考虑如何和何时使用多线程.线程可以大大提高应用程序的可用性和性能,但是当您确定它们将如何与用户界面交互时,需要对其进行非常仔细的考虑. 线程是基本执行单元.单线程执行一系列应用程序指令,并且在应用程序中从头到尾都经由单一的逻辑路径.所有的应用程序都至少有一个线程,

异步调用与回调机制,协程

1.异步调用与回调机制 上一篇我们已经了解到了两组比较容易混淆的概念问题,1.同步与异步调用 2.阻塞与非阻塞状态.在说到异步调用的时候,说到提交任务后,就直接执行下一行代码,而不去拿结果,这样明显存在缺陷,结果是肯定要拿的,这辈子都肯定是要拿到这个结果的,没有这个结果后面的活又不会干,没办法,只能去拿结果的,那么问题是异步调用提交任务后,如何实现既要拿到结果又不需要原地等的理想状态呢?专门为异步调用配备了一个方法--回调机制 先来想想我们之前是怎么拿到一个函数的结果,就传给另外一个函数取执行,

同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式

1. 概念理解        在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:   同步/异步主要针对C端: 同步:      所谓同步,就是在c端发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事.   例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事 异步:      异步的概念和同步相对.当c端一个