基于委托的异步编程实现

神麽是异步调用

在主线程中异步调用的方法不在主线程中执行,而是在另一个辅助线程中与主线程代码并行执行。给出一段示例代码:

当我们调用UploadPictureAsync方法时,图片尚未上传完成,我们就可以在控制台输出提示信息:“图片开始上传”。


/// <summary>
        /// 异步上传图片
         /// </summary>
        /// <param name="fileLocalPath"></param>
        public void UploadPictureAsync(string id, string fileLocalPath)
        {
            DelegateMgr.UploadFileHandler del = new DelegateMgr.UploadFileHandler(UploadFile);
            del.BeginInvoke(id, fileLocalPath, delegate(IAsyncResult ar)
            {
                try
                {
                    string fileUri = del.EndInvoke(ar);
                    FileUploadEventArgs args = new FileUploadEventArgs(id, fileUri);
                    if (PictureUploadCompleted != null)
                    {
                        PictureUploadCompleted(args);
                    }
                }
                catch (Exception ex)
                {
                    LogUtility.LogTableMessage("图片上传异常," + ex);
                }
            }, null);

Console.WriteLine("图片开始上传" );
        }

        private string UploadFile(string id, string filePath)
        {
            string fileUri = string.Empty;
            try
            {
                WebClient wc = new WebClient();
                string targetPath = "http://172.16.50.179:8090/FileUpload/ImageUpLoad.do";
                byte[] bytes = wc.UploadFile(targetPath, "POST", filePath);
                fileUri = Encoding.Default.GetString(bytes);

Console.WriteLine("图片完成上传" );
            }
            catch (Exception exception)
            {
                LogUtility.LogTableMessage("上传图片异常," + exception);
            }

            return fileUri;
        }

        public event Action<FileUploadEventArgs> PictureUploadCompleted;

编译器对委托都做了些神麽。。。

当我们定义一个委托时,编译器会为委托生成一个类。比如我们定义如下委托:

public delegate int DemoDelegate(int a, int b);

编译器会生成如下格式的类:

public sealed class DemoDelegate : MulticastDelegate
    {
        public DemoDelegate(object @object, IntPtr method)
        {
            //
        }

        public virtual int Invoke(int a, int b)
        {
            //方法体为空
        }

        public virtual IAsyncResult BeginInvoke(int a, int b, AsyncCallback callback, object asyncState)
        {
            //方法体为空
        }

        public virtual int EndInvoke(IAsyncResult ar)
        {
            //方法体为空
        }
    }

请注意,上面3个方法都是虚方法virtual,并且方法体都为空。

同步调用实现

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

            DemoDelegate del = new DemoDelegate(Add);

            //同步调用   Console.WriteLine("1 + 2 = " +  del(1, 2));

        }

        static int Add(int a, int b)
        {
            return a + b;
        }
    }

上面这种同步调用方式,实际上调用的是委托类的 Invoke 方法。

异步调用实现

基于委托的异步调用,实际上是通过 BeginInvoke 和 EndInvoke 两个方法来实现的。

我们先来分析一下BeginInvoke方法

public IAsyncResult BeginInvoke(

<输入和输出变量>,

AsyncCallback callback, object asyncState

)

<输入和输出变量>,表示委托声明中,参数有ref或者out修饰的。

callback,异步调用结束时自动回调的方法

asyncState,用于向callback方法提供参数信息,比如回调方法需要一些参数,asyncState 就可以用于填充这些参数。

对BeginInvoke方法的返回类型 IAsyncResult接口的说明

    [ComVisible(true)]
    public interface IAsyncResult
    {
        object AsyncState { get; }
        WaitHandle AsyncWaitHandle { get; }
        bool CompletedSynchronously { get; }
        bool IsCompleted { get; }
    }

AsyncState,直接存储BeginInvoke方法中传入的 asyncState 参数值

AsyncWaitHandle,当异步操作完成时,该句柄处于 signaled 状态。

CompletedSynchronously,表示BeginInvoke是否同步调用完成。

IsCompleted,可以通过循环查询该属性判断异步操作是否完成。

接下来我们分析一下 EndInvoke 方法

public <方法返回值类型> EndInvoke(

<声明为ref或out的参数>,

IAsyncResult result)

调用 BeginInvoke方法会返回一个类型为 IAsyncResult 的对象,该对象会作为 EndInvoke方法的参数,这样EndInvoke方法不断轮询异步执行结果,发现异步调用完成时,会将异步调用结果作为返回值,如果异步调用方法有 ref 或者 out参数,也会负责填充这些参数。

调用者线程                         辅助线程

|

①BeginInvoke     ------------------------>

|                             ②异步调用方法执行

③EndInvoke      <-------------------------

时间: 2024-10-13 19:43:02

基于委托的异步编程实现的相关文章

基于任务的异步编程模式(TAP)

异步编程是C#5.0的一个重要改进,提供两个关键字:async和await.使用异步编程,方法的调用是在后台运行(通常在线程或任务的帮助下),但不会阻塞调用线程.异步模式分为3种:异步模式.基于事件的异步模式和基于任务的异步模式(TAP).TAP是利用关键字async和await实现的,本文将讲解TAP模式.async和await关键字只是编译器的功能.编译器最终会用Task类创建代码. 1.创建任务 建立一个同步方法Greeting,该方法在等待一段时间后,返回一个字符串. private s

异步编程(二)基于事件的异步编程模式 (EAP)

一.引言 在上一个专题中为大家介绍了.NET 1.0中提出来的异步编程模式--APM,虽然APM为我们实现异步编程提供了一定的支持,同时它也存在着一些明显的问题--不支持对异步操作的取消和没有提供对进度报告的功能,对于有界面的应用程序来说,进度报告和取消操作的支持也是必不可少的,既然存在这样的问题,微软当然也应该提供给我们解决问题的方案了,所以微软在.NET 2.0的时候就为我们提供了一个新的异步编程模型,也就是我这个专题中介绍的基于事件的异步编程模型--EAP. 实现了基于事件的异步模式的类将

基于事件的异步编程模式(EAP)

一.引言 在上一个专题中为大家介绍了.NET 1.0中提出来的异步编程模式--APM,虽然APM为我们实现异步编程提供了一定的支持,同时它也存在着一些明显的问题--不支持对异步操作的取消和没有提供对进度报告的功能,对于有界面的应用程序来说,进度报告和取消操作的支持也是必不可少的,既然存在这样的问题,微软当然也应该提供给我们解决问题的方案了,所以微软在.NET 2.0的时候就为我们提供了一个新的异步编程模型,也就是我这个专题中介绍的基于事件的异步编程模型--EAP. 二.介绍 实现了基于事件的异步

基于任务的异步编程模式,Task-based Asynchronous Pattern

术语: APM           异步编程模型,Asynchronous Programming Model EAP           基于事件的异步编程模式,Event-based Asynchronous Pattern TAP           基于任务的异步编程模式,Task-based Asynchronous Pattern

委托的异步编程和同步编程的使用( Invoke 和BeginInvoke)

一,区别: 使用Invoke完成一个委托方法的封送,就类似于使用SendMessage方法来给界面线程发送消息,是一个同步方法.也就是说在Invoke封送的方法被执行完毕前,Invoke方法不会返回,从而调用者线程将被阻塞. 使用BeginInvoke方法封送一个委托方法,类似于使用PostMessage进行通信,这是一个异步方法.也就是该方法封送完毕后马上返回,不会等待委托方法的执行结束,调用者线程将不会被阻塞.但是调用者也可以使用EndInvoke方法或者其它类似WaitHandle机制等待

基于委托的异步回调

异步回调时在调用 BeginInvoke时提供的回调方法,主线程就不必再等待异步线程工作完毕,异步线程在工作结束后会主动调用提供的回调方法. class Program { public delegate void PrintDelegate(string content); static void Main(string[] args) { int threadId = Thread.CurrentThread.ManagedThreadId; PrintDelegate printDeleg

C#秘密武器之异步编程

一.概述 1.什么是异步? 异步操作通常用于执行完成时间可能较长的任务,如打开大文件.连接远程计算机或查询数据库.异步操作在主应用程序线程以外的线程中执行.应用程序调用方法异步执行某个操作时,应用程序可在异步方法执行其任务时继续执行其他的任务. 2.同步与异步的区别 同步(Synchronous):在执行某个操作时,应用程序必须等待该操作执行完成后才能继续执行. 异步(Asynchronous):在执行某个操作时,应用程序可在异步操作执行时继续执行.实质:异步操作,启动了新的线程,主线程与异步线

【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单

一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就具体看看编译器到底在背后帮我们做了哪些复杂的工作的. 二.同步代码存在的问题 对于同步的代码,大家肯定都不陌生,因为我们平常写的代码大部分都是同步的,然而同步代码却存在一个很严重的问题,例如我们向一个Web服务器发出一个

C# 异步编程2 EAP 异步程序开发

在前面一篇博文记录了C# APM异步编程的知识,今天再来分享一下EAP(基于事件的异步编程模式)异步编程的知识.后面会继续奉上TPL任务并行库的知识,喜欢的朋友请持续关注哦. EAP异步编程算是C#对APM的一种补充,让异步编程拥有了一系列状态事件.如果你看过本系列的前一篇文章<C# 异步编程1 APM 异步程序开发>,并假设你是微软C#语言开发组的一员,现在让你来设计基于事件的异步编程模式.那你是会利用之前的APM进行改造?还是进行再次创造呢?所以当你对相关dll进行反编译,会惊喜的发现EA