解析C#中委托的同步调用与异步调用(实例详解)

委托的Invoke方法用来进行同步调用。同步调用也可以叫阻塞调用,它将阻塞当前线程,然后执行调用,调用完毕后再继续向下进行。
同步调用的例子:


代码如下:

using System;
using System.Threading;
public delegate int AddHandler(int a, int b);
public class Foo {
 static void Main() {
  Console.WriteLine("**********SyncInvokeTest**************");
  AddHandler handler = new AddHandler(Add);
  int result = handler.Invoke(1,2);
  Console.WriteLine("Do other work... ... ...");
  Console.WriteLine(result);
  Console.ReadLine();
 }

static int Add(int a, int b) {
  Console.WriteLine("Computing "+a+" + "+b+" ...");
  Thread.Sleep(3000);
  Console.WriteLine("Computing Complete.");
  return a+b;
 }
}运行结果:
**********SyncInvokeTest**************
Computing 1 + 2 ...
Computing Complete.
Do other work... ... ...

同步调用会阻塞线程,如果是要调用一项繁重的工作(如大量IO操作),可能会让程序停顿很长时间,造成糟糕
的用户体验,这时候异步调用就很有必要了。
异步调用不阻塞线程,而是把调用塞到线程池中,程序主线程或UI线程可以继续执行。
委托的异步调用通过BeginInvoke和EndInvoke来实现。
异步调用:


代码如下:

using System;
using System.Threading;
public delegate int AddHandler(int a, int b);
public class Foo {
 static void Main() {
  Console.WriteLine("**********AsyncInvokeTest**************");
  AddHandler handler = new AddHandler(Add);
  IAsyncResult result = handler.BeginInvoke(1,2,null,null);
  Console.WriteLine("Do other work... ... ...");
  Console.WriteLine(handler.EndInvoke(result));
  Console.ReadLine();
 }

static int Add(int a, int b) {
  Console.WriteLine("Computing "+a+" + "+b+" ...");
  Thread.Sleep(3000);
  Console.WriteLine("Computing Complete.");
  return a+b;
 }
}运行结果: **********AsyncInvokeTest**************
Do other work... ... ...
Computing 1 + 2 ...
Computing Complete.

可以看到,主线程并没有等待,而是直接向下运行了。
但是问题依然存在,当主线程运行到EndInvoke时,如果这时调用没有结束(这种情况很可能出现),这时为了等待调用结果,线程依旧会被阻塞。
解决的办法是用回调函数,当调用结束时会自动调用回调函数
回调异步:


代码如下:

public class Foo {
 static void Main() {
  Console.WriteLine("**********AsyncInvokeTest**************");
  AddHandler handler = new AddHandler(Add);
  IAsyncResult result = handler.BeginInvoke(1,2,new AsyncCallback(AddComplete),"AsycState:OK");
  Console.WriteLine("Do other work... ... ...");
  Console.ReadLine();
 }

static int Add(int a, int b) {
  Console.WriteLine("Computing "+a+" + "+b+" ...");
  Thread.Sleep(3000);
  Console.WriteLine("Computing Complete.");
  return a+b;
 }

static void AddComplete(IAsyncResult result) {
  AddHandler handler = (AddHandler)((AsyncResult)result).AsyncDelegate;
  Console.WriteLine(handler.EndInvoke(result));
  Console.WriteLine(result.AsyncState);
 }
}

(0)

相关推荐

  • C#异步调用的好处和方法分享

    异步方法很好的解决了这些问题,异步执行某个方法,程序立即开辟一个新线程去运行你的方法,主线程包括界面就不会死掉了.异步如何开始,好理解,现在我们讨论的是如何结束这个异步出来的新线程. 首先,异步出来的新线程,必须回收,不回收是浪费资源的可耻行为,.NET也是不允许的,所以你别想钻空子,俗话说,请神容易送神难,就是这个道理.下面你可以很容易想到,回收分为2种情况:主动回收和被动回收(当然,这是我自己的理解,微软可不是这么说的),主动回收就是,你去监视那个线程,并且等待,当异步方法完成了,就把异步线

  • C#同步和异步调用方法实例

    复制代码 代码如下: namespace ConsoleTest{    class Program    {        static void Main(string[] args)        {            Console.WriteLine("********同步调用开始**********");            int result = Add(1,2);            Console.WriteLine("同步调用完毕,执行结果为:&

  • C#异步调用示例详解

    本文实例为大家分享了C#异步调用的具体代码,供大家参考,具体内容如下 using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Threading.Tasks; namespace AsyncAppTest { ////异步调用示例详解 /// 第1步:定义委托:此委托的返回值.参数类型必须与要调用的异步方法一致: //

  • C#基础之异步调用实例教程

    本文实例形式展示了C#中异步调用的实现方法,并对其原理进行了较为深入的分析,现以教程的方式分享给大家供大家参考之用.具体如下: 首先我们来看一个简单的例子: 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务 这也是日常生活中很常见的情形,小文的办事效率明显要高于小明.从C#程序执行的角度考虑,小明使用的同步处理方式,而小文则使用的异步处理方式. 同步处理方式下,事务是按顺序一件一件

  • C# 委托的三种调用示例(同步调用 异步调用 异步回调)

    首先,通过代码定义一个委托和下面三个示例将要调用的方法: 复制代码 代码如下: public delegate int AddHandler(int a,int b);    public class 加法类    {        public static int Add(int a, int b)        {            Console.WriteLine("开始计算:" + a + "+" + b);            Thread.Sl

  • C#异步调用实例小结

    本文实例讲述了C#异步调用的方法.分享给大家供大家参考.具体如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Threading; using System.Windows.Forms; namespace CW { public parti

  • java中synchronized(同步代码块和同步方法)详解及区别

     java中synchronized(同步代码块和同步方法)详解及区别 问题的由来: 看到这样一个面试题: //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized (obj){} } synchronized用于解决同步问题,当有多条线程同时访问共享数据时,如果进行同步,就会发生错误,Java提供的解决方案是:只要将操作共享数据的语句在某一时段让一个线程执行完,在执行过程中,其他

  • C++调用Python基础功能实例详解

    c++调用Python首先安装Python,以win7为例,Python路径为:c:\Python35\,通过mingw编译c++代码. 编写makefile文件,首先要添加包含路径: inc_path += c:/Python35/include 然后添加链接参数: ld_flag += c:/Python35/libs/libpython35.a 在源文件中添加头文件引用: #include "Python.h" Python解释器需要进行初始化,完成任务后需要终止: void s

  • Android中webview与JS交互、互调方法实例详解

    Android中webview与JS交互.互调方法实例详解 前言: 对于试水的功能,一般公司都会采用H5的方式来开发,可以用很少的资源与很短的项目工期来完成. 但许多情况下,H5页面会需要一些原生持有的一些如用户信息之类的数据,一些交互也需要调用原生的,如toast之类要保持同一个手机风格一致的交互行为.这个时候就需要能够让JS主动调用原生的方法来进行操作或者获取数据.或者是原生调用JS的方法在H5加载的时候传递一些参数. 对于原生调用JS的方法 我们需要实现一个WebViewClient,在这

  • Laravel框架中队列和工作(Queues、Jobs)操作实例详解

    在我们的web应用中,经常会遇到这样的情况: 用户在进行了某项操作后,我们需要在后台完成一个耗时且耗费资源的任务,以对应用户的操作. 通常来说,web应用中的操作都是同步的(synchronous),即用户的操作可以立即得到回馈. 但是在以上情况下,同步等待操作结果将是灾难性的.比如用户点击了申请密码重置邮件,倘若我们让用户一直停滞在等待页面,直至邮件发送成功,那么用户体验将非常地不好,因为有时候可能需要很长的时间才能将邮件发送完成. 从另一个角度来说,如果我们服务器处于高负荷的情况,当多个用户

  • C++ 中const对象与const成员函数的实例详解

    C++ 中const对象与const成员函数的实例详解 const对象只能调用const成员函数: #include<iostream> using namespace std; class A { public: void fun()const { cout<<"const 成员函数!"<<endl; } void fun() { cout<<"非const成员函数 !"<<endl; } }; int

  • jQuery中的on与bind绑定事件区别实例详解

    on(events,[selector],[data],fn) events:一个或多个用空格分隔的事件类型和可选的命名空间,如"click"或"keydown.myPlugin" . selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代. data:当一个事件被触发时要传递event.data给事件处理函数. fn:该事件被触发时执行的函数. false 值也可以做一个函数的简写,返回false. bind(type,[data],fn) 为每

  • 应用市场中Java拦截器和切面的使用实例详解

    相信大家对拦截器和切面的概念已经不陌生了,本文我们就看一些在应用市场中,拦截器和切面的使用是怎样的. 拦截器的使用:每次接收到某个请求之前,都会调用此拦截器中的方法,其中preHandle方法如果return true,表示继续调用对应的controller,如果return false, public class CheckLoginInterceptor implements HandlerInterceptor { private Logger logger = Logger.getLog

  • PHP中的浅复制与深复制的实例详解

    PHP中的浅复制与深复制的实例详解 前言: 最近温习了一下Design Pattern方面的知识,在看到Prototype Pattern这一设计模式时,注意到其中涉及到一个浅复制与深复制的问题.这里来总结一下,提醒自己以后一定要多加注意. 自PHP5起,new运算符自动返回一个引用,一个 对象变量 已经不再保存整个对象的值,只是保存一个标识符来访问真正的对象内容.当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这

  • web.xml中如何设置配置文件的加载路径实例详解

    web.xml中如何设置配置文件的加载路径实例详解 web应用程序通过Tomcat等容器启动时,会首先加载web.xml文件,通常我们工程中的各种配置文件,如日志.数据库.spring的文件等都在此时被加载,下面是两种常用的配置文件加载路径,即配置文件可以放到 SRC目录下或者可以放到WEB-INF根目录下 第一种在web.xml中这样配置: <context-param> <param-name >contextConfigLocation </param-name >

  • 微信小程序中form 表单提交和取值实例详解

    微信小程序中form 表单提交和取值实例详解 我们知道,如果我们直接给 input 添加 bindinput,比如:<input bindinput="onUsernameInput" />,那么可以在 onUsernameInput 中直接使用 e.detail.value,即: onUsernameInput : function(e) { e.detail.value; } 但是,如果有多个输入控件,我们不可能为每个控件添加 bindinput.bindchange

随机推荐