[转]C#委托的异步调用

本文将主要通过“同步调用”、“异步调用”、“异步回调”三个示例来讲解在用委托执行同一个“加法类”的时候的的区别和利弊。

首先,通过代码定义一个委托和下面三个示例将要调用的方法:

复制代码
/*添加的命名空间
using System.Threading;
using System.Runtime.Remoting.Messaging;
*/
    public delegate int AddHandler(int a,int b);
    
public class 加法类
    {
        
public static int Add(int a, int b)
        {
            Console.WriteLine("开始计算:" + a + "+" + b);
            Thread.Sleep(3000); //模拟该方法运行三秒
            Console.WriteLine("计算完成!");
            
return a + b;
        }
    }
复制代码

同步调用

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

复制代码
public class 同步调用
{
        
static void Main()
        {
            Console.WriteLine("===== 同步调用 SyncInvokeTest =====");
            AddHandler handler = new AddHandler(加法类.Add);
            
int result = handler.Invoke(12);

            Console.WriteLine("继续做别的事情。。。");

            Console.WriteLine(result);
            Console.ReadKey();
        }
        
/*运行结果:
         ===== 同步调用 SyncInvokeTest =====
         开始计算:1+2
         计算完成!
         继续做别的事情。。。
         3       */
}
复制代码

同步调用会阻塞线程,如果是要调用一项繁重的工作(如大量IO操作),可能会让程序停顿很长时间,造成糟糕的用户体验,这时候异步调用就很有必要了。

异步调用

异步调用不阻塞线程,而是把调用塞到线程池中,程序主线程或UI线程可以继续执行。
委托的异步调用通过BeginInvoke和EndInvoke来实现。

复制代码
public class 异步调用
{
        
static void Main()
        {
            Console.WriteLine("===== 异步调用 AsyncInvokeTest =====");
            AddHandler handler = new AddHandler(加法类.Add);

            
//IAsyncResult: 异步操作接口(interface)
            
//BeginInvoke: 委托(delegate)的一个异步方法的开始
            IAsyncResult result = handler.BeginInvoke(12nullnull);

            Console.WriteLine("继续做别的事情。。。");

            
//异步操作返回
            Console.WriteLine(handler.EndInvoke(result));
            Console.ReadKey();
        }
        
/*运行结果:
         ===== 异步调用 AsyncInvokeTest =====
         继续做别的事情。。。
         开始计算:1+2
         计算完成!
         3       */
}
复制代码

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

 异步委托,也可以参考如下写法:

Action<object> action=(obj)=>method(obj);
action.BeginInvoke(obj,ar=>action.EndInvoke(ar),null);

简简单单两句话就可以完成一部操作。

异步回调

用回调函数,当调用结束时会自动调用回调函数,解决了为等待调用结果,而让线程依旧被阻塞的局面。

复制代码
public class 异步回调
{
        
static void Main()
        {
            Console.WriteLine("===== 异步回调 AsyncInvokeTest =====");
            AddHandler handler = new AddHandler(加法类.Add);

            
//异步操作接口(注意BeginInvoke方法的不同!)
            IAsyncResult result = handler.BeginInvoke(1,2,new AsyncCallback(回调函数),"AsycState:OK");
            
            Console.WriteLine("继续做别的事情。。。");
            Console.ReadKey();
        }

        
static void 回调函数(IAsyncResult result)
        {      //result 是“加法类.Add()方法”的返回值

            
//AsyncResult 是IAsyncResult接口的一个实现类,空间:System.Runtime.Remoting.Messaging
            
//AsyncDelegate 属性可以强制转换为用户定义的委托的实际类。
            AddHandler handler = (AddHandler)((AsyncResult)result).AsyncDelegate;
            Console.WriteLine(handler.EndInvoke(result));
            Console.WriteLine(result.AsyncState);
        }
        
/*运行结果:
        ===== 异步回调 AsyncInvokeTest =====
        开始计算:1+2
        继续做别的事情。。。
        计算完成!
        3
        AsycState:OK
                 
*/
}
复制代码

我定义的委托的类型为AddHandler,则为了访问 AddHandler.EndInvoke,必须将异步委托强制转换为 AddHandler。可以在异步回调函数(类型为 AsyncCallback)中调用 MAddHandler.EndInvoke,以获取最初提交的 AddHandler.BeginInvoke 的结果。 

问题:

(1)int result = handler.Invoke(1,2);
为什么Invoke的参数和返回值和AddHandler委托是一样的呢?
答:
Invoke方法的参数很简单,一个委托,一个参数表(可选),而Invoke方法的主要功能就是帮助你在UI线程上调用委托所指定的方法。Invoke方法首先检查发出调用的线程(即当前线程)是不是UI线程,如果是,直接执行委托指向的方法,如果不是,它将切换到UI线程,然后执行委托指向的方法。不管当前线程是不是UI线程,Invoke都阻塞直到委托指向的方法执行完毕,然后切换回发出调用的线程(如果需要的话),返回。
所以Invoke方法的参数和返回值和调用他的委托应该是一致的。

(2)IAsyncResult result = handler.BeginInvoke(1,2,null,null);

BeginInvoke : 开始一个异步的请求,调用线程池中一个线程来执行,
返回IAsyncResult 对象(异步的核心). IAsyncResult 简单的说,他存储异步操作的状态信息的一个接口,也可以用他来结束当前异步。
注意: BeginInvoke和EndInvoke必须成对调用.即使不需要返回值,但EndInvoke还是必须调用,否则可能会造成内存泄漏。

(3)IAsyncResult.AsyncState 属性:
获取用户定义的对象,它限定或包含关于异步操作的信息。 例如:

复制代码
static void AddComplete(IAsyncResult result) 
{   
      AddHandler handler = (AddHandler)result.AsyncState;    
      Console.WriteLine(handler.EndInvoke(result)); 
      。。。。。
}
复制代码

完整代码如下:

复制代码
三个示例的全部代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace ConsoleTest
{
    
public delegate int AddHandler(int a,int b);
    
public class 加法类
    {
        
public static int Add(int a, int b)
        {
            Console.WriteLine("开始计算:" + a + "+" + b);
            Thread.Sleep(3000); //模拟该方法运行三秒
            Console.WriteLine("计算完成!");
            
return a + b;
        }
    }

    
public class 同步调用
    {
        
static void Main()
        {
            Console.WriteLine("===== 同步调用 SyncInvokeTest =====");
            AddHandler handler = new AddHandler(加法类.Add);
            
int result = handler.Invoke(12);

            Console.WriteLine("继续做别的事情。。。");

            Console.WriteLine(result);
            Console.ReadKey();
        }
        
/*运行结果:
         ===== 同步调用 SyncInvokeTest =====
         开始计算:1+2
         计算完成!
         继续做别的事情。。。
         3       */
    }

    
public class 异步调用
    {
        
static void Main()
        {
            Console.WriteLine("===== 异步调用 AsyncInvokeTest =====");
            AddHandler handler = new AddHandler(加法类.Add);

            
//IAsyncResult: 异步操作接口(interface)
            
//BeginInvoke: 委托(delegate)的一个异步方法的开始
            IAsyncResult result = handler.BeginInvoke(12nullnull);

            Console.WriteLine("继续做别的事情。。。");

            
//异步操作返回
            Console.WriteLine(handler.EndInvoke(result));
            Console.ReadKey();
        }
        
/*运行结果:
         ===== 异步调用 AsyncInvokeTest =====
         继续做别的事情。。。
         开始计算:1+2
         计算完成!
         3       */
    }

    
public class 异步回调
    {
        
static void Main()
        {
            Console.WriteLine("===== 异步回调 AsyncInvokeTest =====");
            AddHandler handler = new AddHandler(加法类.Add);

            
//异步操作接口(注意BeginInvoke方法的不同!)
            IAsyncResult result = handler.BeginInvoke(1,2,new AsyncCallback(回调函数),"AsycState:OK");
            
            Console.WriteLine("继续做别的事情。。。");
            Console.ReadKey();
        }

        
static void 回调函数(IAsyncResult result)
        {      //result 是“加法类.Add()方法”的返回值

            
//AsyncResult 是IAsyncResult接口的一个实现类,引用空间:System.Runtime.Remoting.Messaging
            
//AsyncDelegate 属性可以强制转换为用户定义的委托的实际类。
            AddHandler handler = (AddHandler)((AsyncResult)result).AsyncDelegate;
            Console.WriteLine(handler.EndInvoke(result));
            Console.WriteLine(result.AsyncState);
        }
        
/*运行结果:
        ===== 异步回调 AsyncInvokeTest =====
        开始计算:1+2
        继续做别的事情。。。
        计算完成!
        3
        AsycState:OK
                 
*/
    }
}
复制代码

 

来源:http://www.cnblogs.com/yinhu435/archive/2009/10/19/1585958.html

转载于:https://www.cnblogs.com/luohengstudy/p/3158257.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/274182.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vista下载_Vista和视图在游戏设计中的功能

vista下载Views in video games are observation points used to highlight a lot of objects into one frame or shot using a special camera move. Vistas are special types of views that show distant objects, mainly far off landscapes.电子游戏中的视图是观察点&…

keynote使用手册_如何使用Keynote和智能手机为AR创建原型

keynote使用手册Designing for AR is perhaps one of the most interesting applications of UX. As this incredible technology is being put to use for unique applications, UX Designers are tasked with creating user interfaces for an augmented experience, that do…

远程控制工具_不要让您的工具控制您

远程控制工具When to Use Optical Alignment — You’re the Designer. You Know What’s Best.何时使用光学对准—您是设计师。 你知道什么是最好的。 Let’s talk about the tools the vast majority of us use on a day to day basis… These tools are Incredibly powerfu…

模态和非模态代码_我们如何使模态可用和可访问?

模态和非模态代码什么是模态&#xff1f; (What are modals?) A modal, or modal dialog, is an overlay window that opens on top of the current primary content or screen. It places focus on itself, usually making the background inactive (“inert”) — i.e. visu…

如何查看数据文件或者Log文件是否增长过?

在论坛看到一个帖子&#xff0c;说数据库变慢了一段时间&#xff0c;发现这段时间数据库文件的最后修改时间跟变慢的世界一致&#xff0c;想知道这段时间是否文件确实增长了。 其实SQL Server提供了数据增长的Event&#xff0c;而且Default Trace里面就记录了。 下面我们做个测…

软件项目开发 学校自行开发_自行开发游戏

软件项目开发 学校自行开发Making a game is not easy. Quite the contrary; it’s an incredibly difficult and daunting task. Game development typically takes teams of people, thousands of hours worth of labor, and hundreds of thousands — if not millions — of…

jquery Fancybox使用教程

jquery Fancybox使用教程 Fancybox是一款基于jquery的对图片展示播放的插件&#xff0c;当然&#xff0c;它html文本、flash动画、iframe以及ajax也予以支持。还可以通过css自定义外观&#xff0c;阴影效果超级赞&#xff01; 演示效果&#xff1a;http://www.phpddt.com/demo/…

优衣库不雅_Uniqlo主页-用户体验案例研究

优衣库不雅I am a big fan of Uniqlo because they sell innovative clothing that is great quality at great prices. So when all their stores closed during the “Covid-19 Circuit Breaker” in Singapore, I turned to their website and was surprised how difficult …

shields 徽标_到处都有平面徽标

shields 徽标重点 (Top highlight)Companies invest a lot of time, money and energy trying to make audiences remember their logos and associate higher value with it. The end goal is to make customers pick their brand over another brand. 公司投入了大量的时间&a…

登录,注册,登录,登录..?

Last year I found myself in an interesting conversation about which copy to use for a website’s sign up journey. And it wasn’t the first time. Often this devolves into an opinion-based discussion among stakeholders of the ‘what-I-like-based-on-no-eviden…

未完成的控件

using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms;namespace ImageControls {/// <summary>/// 控件/// </summary> public class ShapeEx : Control{#region 字段private Color _B…

ux设计_UX设计101:

ux设计这是什么&#xff1f; (What is this?) This session is part of a learning curriculum that I designed to incrementally skill up and empower a team of Designers and Researchers whose skillset and ways of working needed to evolve to keep up with changes …

idea重要插件代码颜色_颜色在您的网站上的重要性和品牌形象

idea重要插件代码颜色Choosing the right colors for a website or a logo can be a perplexing and time-consuming task, unless you have the right knowledge of colors. Colors play a pivotal role in the success of some businesses and can make a huge impact on the…

【自己给自己题目做】之一:椭圆可点击区域

【题一】请实现以下需求&#xff0c;要做一个活动页面&#xff0c;页面上有一张图片&#xff08;假设是800x600&#xff09;&#xff0c;图片正中心有一个椭圆形的可点击区域&#xff0c;假设椭圆长轴为200px&#xff08;横向&#xff09;&#xff0c;短轴160px&#xff08;纵向…

信息保真度准则_设计保真度的新的非科学公式

信息保真度准则As designers, our audience is more than just our users. We keep our user’s needs top of mind while designing for their jobs-to-be-done, but sometimes we need to illustrate the problem and articulate solutions to a broader audience: our cross…

zend studio配置调试(Xdebug方式)

1.下载xdebug http://xdebug.org/download.php 我下的是PHP 5.4 VC9 (32 bit) 【当前系统php是php5.4.14(win32)版本】 2.配置php.ini 在文件最后配置 [Xdebug]zend_extension "C:/php5.4.14/ext/php_xdebug-2.2.3-5.4-vc9.dll" xdebug.auto_trace1xdebug.collect_p…

人物肖像速写_肖像学的基础

人物肖像速写More in the iconography series:• 7 Principles of Icon Design• 5 Ways to Create a Settings Icon• Icon Grids & Keylines Demystified• Pixel-Snapping in Icon Design• 3 Classic Icon FamiliesAn icon is a compact symbol that represents a disc…

产品设计的Kawaiization

重点 (Top highlight)在过去的一两年中&#xff0c;我注意到品牌和产品设计中出现了某种风格。 (Over the last year or two, I’ve noticed a certain style emerge in brand and product design.) (this article originally appeared on DESK magazine)(本文最初出现在DESK杂…

陌生人社会_陌生人之旅

陌生人社会The Last of Us Part II is a game that is deeply invested in the minutiae of its characters. The pain they cause, the things that drive them, and the particularities of their self-destruction and salvation. The game’s commitment to the true natur…

java数据类型及其说明

Java数据类型及其说明java基本数据类型&#xff1a; java数据类型分为基本数据类型和引用数据类型&#xff0c;基本数据类型就是4类8种&#xff0c;分为数值类型&#xff08;整数型[byte&#xff0c;short&#xff0c;int&#xff0c;long]&#xff09;&#xff0c;字符型&…